๋ฌธ์
๋ฌด๋ค, ๊พธ์ฃผ๋ ๋ฑ ๋ช๋ช ์ฑ๋ค์ ํ๋ฉด์ ์บก์ณํ ๋ฏ ์ด๋ฏธ์งํํด ์ ์ฅ ๋๋ ๊ณต์ ํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ์ค๋์ ์ด ๊ธฐ๋ฅ์ ๊ตฌํํ ์์ ์ธ๋ฐ, ํ๋ฉด ์บก์ณ์์ ๋ ๋์๊ฐ ํ๋ฉด ๋ฐ ์๋๋ก ๋ด์ฉ์ด ๊ณ์ ์ด์ด์ง๋ ScrollView์ ์ ์ฒด ํ๋ฉด์ ์บก์ณํ๋, ์ฆ ์ด๋ฏธ์งํํ๋ ์์
์ ์ ๋ฆฌํ ๊ฒ์ด๋ค.
์ด ๊ธฐ๋ฅ์ ๊ตฌํํ์ฌ UIActivityViewController๋ฅผ ์ฌ์ฉํด ์ด๋ฏธ์ง๋ฅผ ์ธ์คํ๊ทธ๋จ์ ๊ณต์ ํ ์ ์๋ค.
UIGrapics~
UIKit์๋ Image์ PDF ์ ์์ฑํ๊ณ Drawing ํ ์ ์๋ ์ฌ๋ฌ ํด๋์ค์ ํจ์๋ค์ ์ ๊ณตํ๋ค. ์ด๋ฒ์ ์์๋ณผ ํจ์๋ Image์ PDF์ Image Creation ํํธ์ ๋์ค๋ ํจ์ ์ค ์๋ 3๊ฐ์ Drawing์ Shadows/Graphics Context Promitives์ ํจ์ 1๊ฐ์ด๋ค.
ํจ์ ๋ช | ์ค๋ช |
func UIGraphicsBeginImageContext(_ size: CGSize) | ๋นํธ๋งต ๊ธฐ๋ฐ์ ๊ทธ๋ํฝ context๋ฅผ ์์ฑํ๊ณ ์ด context๋ฅผ ํ์ฌ context๋ก ๋ง๋ ๋ค. |
func UIGraphicsBeginImageContextWithOptions( _ size: CGSize, _ opaque: Bool, _ scale: CGFloat ) |
ํน์ ์ต์ ์ ๊ฐ์ง ๋นํธ๋งต ๊ธฐ๋ฐ์ ๊ทธ๋ํฝ context๋ฅผ ์์ฑํ๋ค. |
func UIGraphicsGetImageFromCurrentImageContext() -> UIImage? | ํ์ฌ ๋นํธ๋งต ๊ธฐ๋ฐ์ ๊ทธ๋ํฝ context์ content๋ก๋ถํฐ ์ด๋ฏธ์ง๋ฅผ ๋ฐํํ๋ค. |
func UIGraphicsEndImageContext() |
์คํ์ top์์ ๋นํธ๋งต ๊ธฐ๋ฐ์ ํ์ฌ ๊ทธ๋ํฝ context๋ฅผ ์ ๊ฑฐํ๋ค.
**context๋ stack๊ตฌ์กฐ์ด๋ค
|
ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ context์ ๋ ๋๋ง์ ์ดํดํด์ผํ๋ค. context๊ฐ ์บ ๋ฒ์ค, ๋ ๋๋ง์ด ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ๋ผ๊ณ ์๊ฐํ๋ฉด ์ฝ๋ค.
- UIGraphicBeginImageContext ํจ์: ๊ทธ๋ฆผ์ ๊ทธ๋ฆด ๋ ์บ๋ฒ์ค๊ฐ ๋จผ์ ์ค๋น๋์ด์ผํ๋ค. ๋ฐ๋ผ์ ์บ๋ฒ์ค(context)๋ฅผ ์ค๋นํ๋ค.
- render ํจ์(์๋์์ ์ค๋ช ): ๊ทธํ ํ์ฌ ์ค๋น๋ ์บ๋ฒ์ค์ ๊ทธ๋ฆผ์ ๊ทธ๋ฆฐ๋ค.
- UIGraphicsGetImageFromCurrentImageContext ํจ์: ๊ทธ๋ฆผ์ ๋ค ๊ทธ๋ ธ์ผ๋ฉด ์บ๋ฒ์ค์์ ๊ทธ๋ฆผ์ ๊ฐ์ ธ์จ๋ค.
- UIGrphicsEndImageContext ํจ์: ๋ง์ง๋ง์ผ๋ก ์บ๋ฒ์ค๋ฅผ ์ ๊ฑฐํ์ฌ ํ์ค์ ์ ๋ฆฌํ๋ค.
๋๋ ์ฒซ ๋ฒ์งธ context๋ฅผ ๋ง๋๋ ๊ณผ์ ์์ ๊ทธ๋ฅ BeginImageContext๊ฐ ์๋๋ผ BeginImageContextWithOptions ํจ์๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค. ๊ทธ๋ฅ BeginImageContext ํจ์๋ Options ํจ์์ scale ํ๋ผ๋ฏธํฐ์ ๊ฐ์ด 1.0์ผ๋ก ์ค์ ๋์ด ์๋ค. scale์ ๋นํธ๋งต์ ํฌ๊ธฐ๋ฅผ ๊ตฌํ๊ธฐ ์ํด ๋๋น, ๋์ด์ ํจ๊ป ๊ณฑํด์ ธ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ ํ๋ค. ๋ฐ๋ผ์ ํ์ง์๋ ์ํฅ์ ๋ฏธ์ณ ๋ฎ์ ํ์ง์ ์ด๋ฏธ์ง๊ฐ ๋ฐํ๋๋ค. scale์ด 0.0์ ๊ฒฝ์ฐ ๊ธฐ๊ธฐ์ ํ๋ฉด scale์ ์๋ฏธํ์ฌ ์ข์ ํ์ง์ ์ด๋ฏธ์ง๋ฅผ ๋ฐํ๋ฐ์ ์ ์๋ค.
์์ ๊ฐ์ ์ด์ ๋ก UIGraphicsBeginImageContextWithOptions ํจ์๋ฅผ ์ฌ์ฉํ์ฌ scale์ ์กฐ์ ํด์ค ๊ฒ์ด๋ค.
Rendering
๋ ๋๋ง์ ์ ์ค๋ช ์์ ์ ์ ์๋ฏ์ด ๊ทธ๋ฆผ์ ๊ทธ๋ฆฌ๋ ๊ฒ์ด๋ค. ๋ ๋๋งํ๋ ํจ์ ๋ํ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋ค.
๋ฉ์๋ ๋ช | ์ค๋ช |
func drawHierarchy( in rect: CGRect, afterScreenUpdates afterUpdates: Bool ) -> Bool | ํ์ฌ context์ ํ๋ฉด์ ๋ณด์ด๋ ๊ฒ์ฒ๋ผ ์์ ํ view ๊ณ์ธต์ snapShot์ ๋ ๋๋งํ๋ค. ์ด ๋ฉ์๋๋ view ์ด๋ฏธ์ง์ ๋ธ๋ฌ์ ๊ฐ์ ๊ทธ๋ํฝ ํจ๊ณผ๋ฅผ ๋ฃ๊ณ ์ ํ ๋ ์ฌ์ฉํ๋ค. |
func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? | ํ์ฌ view์ content์ ๊ธฐ๋ฐํ snapShot์ ๋ฐํํ๋ค. ์ด๋ฏธ ๋ ๋๋ง๋ ํ์ฌ view์ ๋ชจ์ต์ capture ํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ drawHierarchy ํจ์๋ณด๋ค ์๋๊ฐ ๋น ๋ฅด๋ค. |
func render(in ctx: CGContext) | ์ ๊ณต๋ context์ ํด๋น layer์ ํ์ layer๋ฅผ ๋ ๋๋งํ๋ค. |
์ฐ๋ฆฌ๋ ํ๋ฉด ์๋ฟ๋ง ์๋๋ผ ๋ฐ์ผ๋ก ๊ฐ๋ ค์ง ๋ถ๋ถ ๋ํ ๋ ๋๋งํด์ผํ๊ธฐ ๋๋ฌธ์ render ํจ์๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค.
ScrollView์ Content ์์ญ
ScrollView๋ frame๊ณผ content ์์ญ์ ์๋ฏธ๊ฐ ๋ค๋ฅด๋ค. scrollView ์์ ๋ด์ฉ์ด ๊ธธ์ด์ง๋ค๋ฉด ๊ทธ๊ฑด content์ ์์ญ์ด ๊ธธ์ด์ง์ ์๋ฏธํ๋ค. ์ฆ scrollView.contentSize๊ฐ ๋ฌ๋ผ์ง๋ ๊ฒ์ด๋ค.

์ด ์ ์ผ๋ก ๋ณด์์ ์ฐ๋ฆฌ๋ scroll์ frame์ด contentSize๋งํผ ๋์ด๋์ผ ํ๋ค๋ ๊ฑธ ์ ์ ์๋ค. ๋ํด์ contentOffset์ .zero(x:0, y:0)๋ก ๋ณ๊ฒฝํด content๊ฐ ์ฒ์ ๋ด์ฉ๋ถํฐ ์ ๋ ๋๋ง๋ ์ ์๊ฒ ํด์ผํ๋ค.
๋ ๋๋ง ๋ฌธ์
render ํจ์๋ ํด๋น ๋ทฐ์ layer์ ํ์ layer๋ฅผ ๋ ๋๋งํ๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ scrollView๋ฟ๋ง ์๋๋ผ ๊ทธ SuperView์ธ view์ frame๋ contentSize๋งํผ ์กฐ์ ํ ๊ฒ์ด๋ฉฐ scrollView๊ฐ ์๋ view์ layer๋ฅผ ๋ ๋๋ง ํ ๊ฒ์ด๋ค.
์๋ํ๋ฉด render๊ฐ ํด๋นํ๋ view์ layer๋ฅผ ๋ ๋๋งํด์ฃผ์ง๋ง ๋ง์ฝ self.view.frame, ์ฆ ๊ธฐ๊ธฐ์ ํ๋ฉด์ ๊ฐ๋ ค์ ธ ์ ๋ณด์ด๋ ๋ถ๋ถ์ ๋ ๋๋งํด์ฃผ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ ์ฌ์ง์ ๊ฒ์์ ๋ถ๋ถ์ด ๋ฐ๋ก ๋ ๋๋ง๋์ง ์์ context ๋ถ๋ถ์ด๋ค.

๋ view.frame์ contentSize๋ก ์กฐ์ ํ์ง ์์ผ๋ฉด scrollView์ content๊ฐ ์งง์๋ ํ๋ฉด์ ํฌ๊ธฐ๋งํผ ๋ ๋๋ง๋๊ธฐ ๋๋ฌธ์ content ์์ญ๋ง ๋ ๋๋งํ๊ธฐ ์ํด์๋ frame์ ์กฐ์ ํ ํ์๊ฐ ์๋ค.

๋ ์ ๊ฒฝ์จ์ผ ํ ๋ถ๋ถ์ AutoLayout์ safeAreaLayoutGuide์ ์ค์ ํ๋์ง ์๋ SuperView์ธ view์ ์ค์ ํ๋์ง์ด๋ค. ์ด์ ๋ฐ๋ผ NavigationBar ์ฌ์ด์ฆ๋งํผ ์ค์ฐจ๊ฐ ์๊ธธ ์๋ ์๋ค.
๊ตฌํ
extension UIView {
func snapShotFullScreen(scrollView: UIScrollView) -> UIImage? {
//scrollView์ contentSize๋งํผ scrollView.frame๊ณผ self.view.frame์ ํฌ๊ธฐ๋ฅผ ์กฐ์
//๊ทธ๋ฆฌ๊ณ scrollView๊ฐ ์๋ self.view์ layer๋ฅผ ๋ ๋๋งํ๋ค.
//๊ทธ ํ scrollView.frame๊ณผ self.view.frame์ ์์๋ณต๊ตฌํ๋ค.
//์ฆ self.view.frame์ ์์ญ๋งํผ context(์บ ๋ฒ์ค)๋ฅผ ๋ง๋ค๊ณ ๊ทธ ์์ญ๋งํผ ๋ ๋๋ง(๊ทธ๋ฆฌ๊ธฐ)ํ๋ ๊ณผ์ ์ด๋ค.
let savedFrame = self.frame
let savedScrollviewFrame = scrollView.frame
let savedContentOffset = scrollView.contentOffset
let scrollFrame = CGRect(x: 0, y: 0, width: scrollView.contentSize.width, height: scrollView.contentSize.height)
scrollView.contentOffset = .zero
scrollView.frame = scrollFrame
self.frame = scrollFrame
//context๋ stack ๊ตฌ์กฐ
//ํด๋น ์ต์
์ ๊ฐ์ง Context๋ฅผ ํ๋ ์์ฑ
//์บ ํผ์ค ์ค๋น
UIGraphicsBeginImageContextWithOptions(self.frame.size, true, 0.0)
//๊ทธ๋ฆฌ๊ธฐ
//์์์ ๋ง๋ context์ ํ์ฌ ๋ณด์ฌ์ง๊ณ ์๋ ํ๋ฉด ๋ ๋๋ง
self.layer.render(in: UIGraphicsGetCurrentContext()!)
//ํ์ฌ ์ด๋ฏธ์ง๊ฐ ๊ทธ๋ ค์ง context์์ ์ด๋ฏธ์ง ๊ฐ์ ธ์ค๊ธฐ
guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
scrollView.contentOffset = savedContentOffset
scrollView.frame = savedScrollviewFrame
self.frame = savedFrame
//์บ ํผ์ค ํ๊ธฐ
//context pop
UIGraphicsEndImageContext()
return image
}
}
+ iOS 17 ์ด์์์๋ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ
[ iOS ] ํ๋ฉด ์บก์ณํ๊ธฐ - UIGraphicsRenderer
๐ซ ๋ฌธ์ ๋ฐ์ iOS 17๊ฐ ๋ฐํ๋๋ฉฐ, ์ฑ์คํ ์ด์ ๋ฐฐํฌํ ์๋น์ค์ ํน์ deprecated๋ ํด๋์ค๋ ๋ฉ์๋๊ฐ ์์๊น ์ถ์ด ์ฐพ์๋ดค๋ค. ์ ๋ง ์ํ๊น๊ฒ๋ '์ด๋ฏธ์ง ๊ณต์ ํ๊ธฐ' ๊ธฐ๋ฅ์์ ์ฌ์ฉํ๋ UIGraphicsBeginImageCo
88yhtserof.tistory.com
'iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ iOS ] ๋๊ธฐ์ ๋น๋๊ธฐ / ์ง๋ ฌ๊ณผ ๋์์ฑ (0) | 2023.06.22 |
---|---|
[ iOS ] CollectionView์ Section ์จ๊ธฐ๊ธฐ - CompositionalLayout (0) | 2023.03.06 |
[ iOS ] UserDefaults - ์ปค์คํ ํ์ ์ ์ฅํ๊ธฐ (Attempt to insert non-property list object ์ค๋ฅ) (0) | 2023.01.21 |
[ iOS ] Property list (0) | 2023.01.20 |
[ iOS ] ๊ณต์ ํ๊ธฐ ๊ธฐ๋ฅ ๊ตฌํ - UIActivityViewController (0) | 2023.01.03 |