๐ซ ๋ฌธ์ ๋ฐ์
iOS 17๊ฐ ๋ฐํ๋๋ฉฐ, ์ฑ์คํ ์ด์ ๋ฐฐํฌํ ์๋น์ค์ ํน์ deprecated๋ ํด๋์ค๋ ๋ฉ์๋๊ฐ ์์๊น ์ถ์ด ์ฐพ์๋ดค๋ค. ์ ๋ง ์ํ๊น๊ฒ๋ '์ด๋ฏธ์ง ๊ณต์ ํ๊ธฐ' ๊ธฐ๋ฅ์์ ์ฌ์ฉํ๋ UIGraphicsBeginImageContextWithOptions(_:_:_:)๊ฐ iOS 17.0 ๋ฒ์ ๊น์ง๋ง ์ ๊ณต๋๋ค๊ณ ํ๋ค...
๊ทธ๋์ ์ด๋ป๊ฒ ๋ฒ์ ์ ์ ํ ๊น ๊ฑฑ์ ํ๋ฉฐ ๊ณต์ ๋ฌธ์์์ Graphic, Image, Render๋ฅผ ํค์๋๋ก ๋น์ทํ ๊ธฐ๋ฅ์ ํ๋ ํด๋์ค ๋๋ ๋ฉ์๋๋ฅผ ์ฐพ์๋ดค๋ค. ๋คํํ ๋ฉ์ง ์๊ฒ Drawing ์นดํ ๊ณ ๋ฆฌ์์ UIGraphicsRenderer ํด๋์ค๋ฅผ ๋ฐ๊ฒฌํ๋ค! ์ด์ ์ด ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ iOS 17 ์ดํ๋ฅผ ๋์ํ๋ ๋ฆฌํฉํ ๋ง์ ์์ํด๋ณด์.
๐จ UIGraphicsRenderer
UIGraphicsRenderer
An abstract base class for creating graphics renderers.
๊ทธ๋ํฝ ๋ ๋๋ฌ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์ถ์์ ์ธ ๊ธฐ๋ณธ ํด๋์ค
์ด ํด๋์ค๋ ์ถ์ํ๋ ๊ธฐ๋ณธ ํด๋์ค๋ก, ์ง์ ์ ์ผ๋ก ์ฌ์ฉํ ์๋ ์์ผ๋ฉฐ subclassing์ด ํ์ํ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก image์ PDF๋ฅผ ์ํ ํ์ ๊ตฌํ ํด๋์ค๊ฐ ์ ๊ณต๋๋ฉฐ, ๋ ๋ค์ํ๊ณ ํ์ํ ์์ธ ๊ธฐ๋ฅ์ ์ํด ์ง์ ํ์ ํด๋์ค๋ฅผ ๊ตฌํํ์ฌ ์ฌ์ฉํ ์๋ ์๋ค.
UIGraphicsImageRenderer / UIGraphicsPDFRenderer
๊ทธ๋ํฝ ๋ ๋๋ฌ๋ Core Graphics Contexts์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ ๊ด๋ฆฌ๋ฅผ ์ ๊ณตํ๋ค. ์ด Core Graphics Contexts๋ 2D Graphics์ ๋ํ ๋๋ก์ ํ๊ฒฝ๊ณผ ๋ฐฑ์ ์ ์ฅ์(backing store)๋ฅผ ๋ํ๋ธ๋ค. ๊ทธ๋ํฝ ๋ ๋๋ฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ฉด, Core Graphics Contexts๋ ์ฌ์ฌ์ฉํ๋ค.
backing store:
swap device๋ก, ํ๋์จ์ด์ ์ํ๋ค. ์ฌ๊ธฐ์ swap์ด๋ ์์คํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ ๊ฒฝ์ฐ ํ๋์จ์ด์ ์ผ๋ถ๋ฅผ ํ์ฉํ์ฌ ์์ ์ ๋์์ฃผ๋ ๊ฒ์ด๋ค. ๋จ์ด์ ํ๊ธ ๋ป์ด '๊ตํ'์ด๋ฏ, ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์์ ์ง๊ธ ๋น์ฅ ํ์ํ์ง ์์ ๋ถ๋ถ๊ณผ ํ์ํ ๋ถ๋ถ์ swap-in / swap-out ํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ๋ณดํ ์ ์๊ฒ ๋๋๋ค.
๐ฉ๐ป๐จ UIGraphicsImageRenderer
UIGraphicsImageRenderer
A graphics renderer for creating Core Graphics-backed images.
Core Graphics ์ง์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๋ ๊ทธ๋ํฝ ๋ ๋๋ฌ์ด๋ค.
UIGraphicsImageRenderer๋ฅผ ์ฌ์ฉํ๋ฉด, ๊ฐ ์ ์์๋ฅผ ํํํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๋นํธ ์(์ ์ฌ๋)์ ์ด๋ฏธ์ง ๊ท๋ชจ๋ฅผ ๊ตฌ์ฑํ๋๋ฐ ์ ๊ฒฝ ์ธ ํ์์๋ค. ๊ฒ๋ค๊ฐ Core Graphics Contexts๋ฅผ ๊ด๋ฆฌํ์ง ์์๋ ๋๋ก์ ์์ ์ ํ ์ ์๋ค. ์ด๋ฏธ์ง ์ถ๋ ฅ ํฌ๊ธฐ์ ํฌ๋งท ์ค์ ํ๋ผ๋ฏธํฐ๋ก ์ด๋ฏธ์ง ๋ ๋๋ฌ๋ฅผ ์ด๊ธฐ ์ค์ ํ ์ ์๋ค. ๊ทธ๋ฐ ํ ์ด ๋ ๋๋ฌ์ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ๊ทธ๋ฆด ์ ์๋ค.
์ด์ ์ ์ฌ์ฉํ๋ UIGraphicsBeginImageContextWithOptions์ ๊ฒฝ์ฐ, ๋๋ก์ ํ๊ฒฝ์ ๋ฐ๋ก ๊ตฌ์ฑํ์ด์ผ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ํจ์์์ context ์ธ์คํด์ค๊ฐ ๋ฐํ๋์ด ์ฌ์ฉํ๋ ๊ฒ์ด ์๋๋ผ, ์ ์ด๋๊ฐ์ ๋ง๋ค์ด์ง context๊ฐ ์คํ์ผ๋ก ์์ฌ ํ์ฌ context๋ก ์ฌ์ฉ๋๋ ๊ตฌ์กฐ์ฌ์ ์ง๊ด์ ์ธ ์ฌ์ฉ์ด ์ด๋ ค์ ๋ค.
ํ์ง๋ง ์ด ํด๋์ค๋ฅผ ํตํด ๊ทธ๋ํฝ ์ด๋ฏธ์ง ๋ ๋๋ฌ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์์ด ๋ ๋๋ฌ ์ฌ์ฉ์ด ์ง๊ด์ ์ด์ด์ ์ข์๋ค.
๐๏ธ ํ๋ฉด์ ์ด๋ฏธ์ง๋ก ๋ ๋๋งํ๊ธฐ
UIGraphicsImageRenderer์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋, ์ด๋ฏธ์ง ์ถ๋ ฅ ํฌ๊ธฐ์ Context ์์ฑ ์ ์ฌ์ฉํ ํฌ๋งท์ ํ๋ผ๋ฏธํฐ๋ก ์ค์ ํ ์ ์๋ค. ๋๋ ๊ธฐ๋ณธ ํฌ๋งท์ ์ฌ์ฉํ ์์ ์ด๋ผ ๋ฐ๋ก ํฌ๋งท ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์์๋๋ฐ, UIGraphicsImageRendererFormat ํด๋์ค๋ฅผ ์ฌ์ฉํด ์ํ๋ ํฌ๋งท์ ๋ง๋ค ์๋ ์๋ค.
// Render Image
let renderer = UIGraphicsImageRenderer(size: self.frame.size)
๊ทธ๋ํฝ ๋ ๋๋ฌ์๋ ์ธ ๊ฐ์ง ํํ์ ์ถ๋ ฅ์ ์ ๊ณตํ๋ค. UIImage๋ฅผ ๋ฐํํ๋ image(actions:), jped๋ก ์ธ์ฝ๋ฉ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ jpegData(withCompressionQuality:actions:), png๋ก ์ธ์ฝ๋ฉ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ pngData(actions:)์ด ์๋ค.
๋๋ ๊ธฐ์กด์ UIImage๊ฐ ๋ฐํ๋๋๋ก ๊ตฌํํ๊ธฐ์ ๊ทธ๋๋ก ๋ฐํ๊ฐ์ ์ ์งํ๊ณ ์ image(actions:)๋ฅผ ์ฌ์ฉํ๋ค.
let image = renderer.image { context in
// ์ฝ๋
}
๊ทธ ๋ค์ ๋ฌด์์ ๋ ๋๋งํ ์ง๋ฅผ ์ ํด์ ์ด context์ ๋๊ฒจ ์ฃผ์ด์ผ ํ๋ค. ๋๋ ํ๋ฉด์ ๊ทธ๋ฆฌ๊ณ ์ถ์๊ธฐ ๋๋ฌธ์ view.layer์ ๋ฉ์๋์ธ render(in:) ์ ์ฌ์ฉํ๋ค.
์ฌ๊ธฐ์ renderer, context, view, UIImage(๊ฒฐ๊ณผ)๋ฅผ ํท๊ฐ๋ฆฌ์ง ์๊ฒ ๊ตฌ๋ถํ์๋ฉด(๋ด๊ฐ ์๊ฐํ ๋๋) ์๋์ ๊ฐ๋ค.
๐ฉ๐ป๐จ(ํ๊ฐ) Renderer / ๐ชง(๋ํ์ง) Context / โฐ๏ธ(๋์) View / ๐๏ธ(์์ฑ๋ ๊ทธ๋ฆผ) UIImage
let image = renderer.image { context in
self.layer.render(in: context.cgContext) // View๋ฅผ Extension ํ๊ธฐ ๋๋ฌธ์ self ์ฌ์ฉ
}
๐ธ ScrollView ์ ์ฒด ์บก์ณํ๊ธฐ
ScrollView์ ๊ด๋ จํด ๋ ๋๋ง ํฌ๊ธฐ๋ฅผ ๊ตฌํ๋ ๋ฐฉ๋ฒ์ ์ด์ ๊ธ์์ ํ์ธํ ์ ์๋ค.
๐ง๐ปโ๏ธ ์ ์ฒด ์ฝ๋ ํ์ธํ๊ธฐ
import UIKit
extension UIView {
/// Render a Image from view to get a full screen snap shot.
/// Return UIImage, or nil.
func snapShotFullScreen(scrollView: UIScrollView) -> UIImage? {
let savedFrame = self.frame
let savedScrollviewFrame = scrollView.frame
let savedContentOffset = scrollView.contentOffset
let scrollContentFrame = CGRect(x: 0, y: 0, width: scrollView.contentSize.width, height: scrollView.contentSize.height)
scrollView.contentOffset = .zero
scrollView.frame = scrollContentFrame
self.frame = scrollContentFrame
// Render Image
let renderer = UIGraphicsImageRenderer(size: self.frame.size)
let image = renderer.image { context in
self.layer.render(in: context.cgContext)
}
// Initialize the set value
scrollView.contentOffset = savedContentOffset
scrollView.frame = savedScrollviewFrame
self.frame = savedFrame
return image
}
}
๐ค ๋ฆฌํฉํ ๋งํ๋ฉฐ ๋๋ ์
๊ธฐ์กด์ ์ฌ์ฉํ๋ UIGraphicsBeginImageContextWithOptions ํจ์๊ฐ ์ค๋๋๊ธฐ๋ ํ์ง๋ง, ์ด์ฌํ ๊ณต๋ถํ๊ณ ๋ง๋ ๊ธฐ๋ฅ์ ๋ฒ์ ์ ์ ์ด์ ๋ก ๋ฆฌํฉํ ๋งํด์ผํ๋ ์์ฌ์์ด ์ปธ๋ค. ํ์ง๋ง ๋ค๋ฅธ ๊ตฌํ ๋ฐฉ๋ฒ์ ์์๋ณด๊ณ ๋ค๋ฅธ ํด๋์ค๋ก ๊ตฌํํด๋ณด๋ ์ Apple์์ deprecatedํ๋์ง ์ ์ ์์๋ค. ์๋ก ์ฌ์ฉํ ํด๋์ค๋ ๊ณต๋ถ๊ฐ ์ฌ์ ๊ณ , ๋ถํ์ํ๋ค๊ณ ๋๊ปด์ง๋ ๋ถ๋ถ์ด ์์๋ค. ๊ฒ๋ค๊ฐ ๋ฆฌํฉํ ๋ง์ ํ๋ ์ฝ๋ ๋ ์ง๊ด์ ์ด๊ณ ๊ฐ๋จํด์ก๋ค. ์ด๋ฒ์ ์ฌ์ฉํ UIGraphicRenderer๋ iOS 10 ๋ถํฐ ์ฌ์ฉ๋๋ ํด๋์ค๋ผ ์ฌ์ค ์ค๋๋ ํธ์ด์ง๋ง, visionOS์์๋ ์ง์๋๊ณ ์ค์ ๊ตฌํ์๋ ์ด๋ ค์์ด ์์ด์ ํ๋์์ ๊ณ์ ์ฌ์ฉํ ์ ์์ ๊ฒ ๊ฐ๋ค.
'iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ iOS ] ๋ฐ์ดํฐ ์ ๋ฌด์ ๋ฐ๋ผ CollectionView UI ๋ณ๊ฒฝํ๊ธฐ with DiffableDataSource, Snapshot (1) | 2024.06.17 |
---|---|
[ iOS ] ์๋ ์ฐธ์กฐ ์นด์ดํ , ARC (Automatic Reference Counting) (0) | 2024.03.27 |
[ iOS ] ์ด๊ฑฐํ์ ์์๊ฐ์ผ๋ก ํํ ์ฌ์ฉํ๊ธฐ (2) | 2023.12.01 |
[ iOS ] MVC - 3 ) Controller ๊ฐ์ฒด (0) | 2023.11.18 |
[ iOS ] MVC - 2 ) Model ๊ฐ์ฒด (0) | 2023.11.18 |