ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ScreenShot(Save, Share)
    오늘의 Swift 상식 2021. 10. 22. 17:32
    728x90
    반응형

     

     

     

     

     

     

    안녕하세요. iOS 개발자 에이든입니다!👦🏻

     

     

     

    ☕️스타벅스, 🚕카카오택시 등 우리가 자주 사용하는 App들의 영수증을 저장해 보고 공유하신 적 있으신가요?

    저는 회사에 영수증 제출할 때 그 기능을 많이 써본 것 같아요ㅎㅎㅎㅎ

    무언가를 구매하는 App들에는 이런 기능들이 자주 사용되는데

    오늘은 이 기능에 대한 내용을 공유하고자 합니당ㅋㅋㅋㅋㅋ

     

    늘 그렇듯 코드는 SwiftUI 기준이고, ViewController를 사용하시는 분들은

    하단 코드에 View를 Extension 하는 과정 없이 바로 UIView에 적용시키면 됩니다!

     

    그럼 시~~~~~작!

     


     

     

     


    ScreenShot

     

    일단! 우리가 스크린샷을 찍고 저장까지 할 거니깐!

    권한부터 설정해줍시다!

     

    Xcode13부터는 Info.plist TARGETS 내부로 이동했죠!

     

    Info로 가서

    Privacy - Photo Library Usage Description을 추가해주고

    왜 권한이 필요한지 설명을 달아줍시당!

     

     

     

     

     

     

    일단 코드를 좀 더 깔끔하고, 수정하기 쉽도록 

    ScreenShot 기능을 UIView, View에 Extension으로 Method를 만들어 주겠습니다!

    ViewController를 사용하시는 분은 UIView만 하시면 됩니당!

    먼저 ScreenShot을 찍기 위해선 UIGraphicsBeginImageContextWithOptions(_:_:_:)Option들을 정해주고, 
    UIGraphicsGetCurrentContext()를 사용하여 현재 Context를 가져온 뒤 UIGraphicsGetImageFromCurrentImageContext()로 현재의 Context를 UIImage로 변환하면 현재의 최 상단에 있는 View를 UIImage로 뽑을 수 있게 됩니다!
    func UIGraphicsBeginImageContextWithOptions(_ size: CGSize, 
                                              _ opaque: Bool, 
                                              _ scale: CGFloat)​

    ∙ size: 갤러리에 저장할 이미지
    ∙ opaque: 불투도. 완전히 불투명하면 true, 부분적으로 투명하면 false이고 알파값이 들어가야 합니다.
    ∙ scale: 배율
    // UIView에 ScreenShot을 넣기 위함
    extension UIView {
        var screenShot: UIImage {
            let rect = self.bounds
            UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
            let context: CGContext = UIGraphicsGetCurrentContext()!
            self.layer.render(in: context)
            let capturedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            return capturedImage
        }
    }
    
    // View에 ScreenShot을 넣기 위함
    extension View {
        func takeScreenshot(origin: CGPoint, size: CGSize) -> UIImage {
            let window = UIWindow(frame: CGRect(origin: origin, size: size))
            // UIHostingController: SwiftUI View들을 관리하기 위한 ViewController
            let hosting = UIHostingController(rootView: self)
            hosting.view.frame = window.frame
            window.addSubview(hosting.view)
            window.makeKeyAndVisible()
            return hosting.view.screenShot
        }
    }

     

     

     

     

     


    갤러리에 저장하기

    UIImageWriteToSavedPhotosAlbum(_:_:_:_:)를 사용하면 바로 갤러리에 이미지를 저장할 수 있습니다!
    func UIImageWriteToSavedPhotosAlbum(_ image: UIImage, 
                                      _ completionTarget: Any?, 
                                      _ completionSelector: Selector?, 
                                      _ contextInfo: UnsafeMutableRawPointer?)​

     

    ∙ image: 갤러리에 저장할 이미지
    completionTarget: Call Back 받을 Object
    completionSelector: Call Back Method
    contextInfo: completionSelector에 전달할 정보

    func screenShot() {
        let screenshot = body.takeScreenshot(origin: UIScreen.main.bounds.origin, size: UIScreen.main.bounds.size)
            
        // 사진권한이 허용 되어 있으면 저장
        PHPhotoLibrary.requestAuthorization( { status in
            switch status {
            case .authorized:
                UIImageWriteToSavedPhotosAlbum(screenshot, self, nil, nil)
                showingAlert = true
            case .denied:
                break
            case .restricted, .notDetermined:
                break
            default:
                break
            }
        })
    }

     

     

     

     

     


    공유하기

    이 녀석은 UIActivityViewController로 공유 및 복사 등 다양한 작업을 할 수 있는 ViewController를 띄웁니다. 그래서 공유를 하고 싶으면 이 녀석만 호출해서 띄우면 끝!
    func share() {
        let screenshot = body.takeScreenshot(origin: UIScreen.main.bounds.origin, size: UIScreen.main.bounds.size)
        let activityViewController = UIActivityViewController(activityItems: [screenshot], applicationActivities: nil)
        UIApplication.shared.windows.first?.rootViewController?.present(activityViewController, animated: true)
    }

     

     

     

     

     


    전체 Code, 결과

    import SwiftUI
    import Photos // PHPhotoLibrary를 활용해서 갤러리 권한은 확인하기 위함
    
    struct ContentView: View {
        // MARK: Property
        @State private var showingAlert: Bool = false
        
        // MARK: View
        var body: some View {
            VStack {
                ZStack {
                    HStack(alignment: .center) {
                        Spacer()
                        
                        Image(systemName: "square.and.arrow.down")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 25, height: 25, alignment: .center)
                            .onTapGesture {
                                screenShot()
                            }
                        
                        Spacer().frame(width: 15)
                        
                        Image(systemName: "square.and.arrow.up")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 25, height: 25, alignment: .center)
                            .onTapGesture {
                                share()
                            }
                        
                        Spacer().frame(width: 20)
                    }
                    .frame(height: 34)
                    
                    Text("스크린샷 및 공유")
                }
                .padding(EdgeInsets(top: 5, leading: 0, bottom: 0, trailing: 0))
                
                Divider()
                    .frame(width: UIScreen.main.bounds.width, height: 1, alignment: .center)
                    .background(Color.gray)
                    .opacity(0.3)
                
                VStack {
                    Spacer()
                    
                    Image(systemName: "airtag.fill")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 250, height: 250, alignment: .center)
                        .foregroundColor(.white)
                    
                    Spacer()
                }
                .frame(width: UIScreen.main.bounds.width)
                .background(Color.black.ignoresSafeArea(edges: [.leading, .trailing, .bottom]))
            }
            .background(Color.white)
            .alert(isPresented: $showingAlert) {
                Alert(title: Text("저장 완료"), message: Text("스크린샷이 저장되었습니다."), dismissButton: .default(Text("확인")))
            }
        }
    }
    
    extension ContentView {
        /// 이미지 저장
        func screenShot() {
            let screenshot = body.takeScreenshot(origin: UIScreen.main.bounds.origin, size: UIScreen.main.bounds.size)
            UIImageWriteToSavedPhotosAlbum(screenshot, self, nil, nil)
            
            // 사진권한이 허용 되어 있으면 저장
            PHPhotoLibrary.requestAuthorization( { status in
                switch status {
                case .authorized:
                    showingAlert = true
                case .denied:
                    break
                case .restricted, .notDetermined:
                    break
                default:
                    break
                }
            })
        }
        
        /// 이미지 공유
        func share() {
            let screenshot = body.takeScreenshot(origin: UIScreen.main.bounds.origin, size: UIScreen.main.bounds.size)
            let activityViewController = UIActivityViewController(activityItems: [screenshot], applicationActivities: nil)
            UIApplication.shared.windows.first?.rootViewController?.present(activityViewController, animated: true)
        }
    }
    
    // UIView에 ScreenShot을 넣기 위함
    extension UIView {
        var screenShot: UIImage {
            let rect = self.bounds
            UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
            let context: CGContext = UIGraphicsGetCurrentContext()!
            self.layer.render(in: context)
            let capturedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            return capturedImage
        }
    }
    
    // View에 ScreenShot을 넣기 위함
    extension View {
        func takeScreenshot(origin: CGPoint, size: CGSize) -> UIImage {
            let window = UIWindow(frame: CGRect(origin: origin, size: size))
            let hosting = UIHostingController(rootView: self)
            hosting.view.frame = window.frame
            window.addSubview(hosting.view)
            window.makeKeyAndVisible()
            return hosting.view.screenShot
        }
    }

     

     

     


    🖼 갤러리에 저장하기 🖼

     

     

    👨‍👩‍👦‍👦 공유하기 👨‍👩‍👦‍👦

     

     

     


     

    오늘은 화면 ScreenShot과 이를 저장하고, 공유하는 법에 대해 알아보았습니당!

    이것만 했는데도 뭔가 있어 보이네요ㅎㅎㅎㅎㅎ

     

    공유하는 건 UIActivityController 하나만 띄워도 다양한 기능을 활용할 수 있으니 편리해서 넘 좋..🥺

     

    혹시라도 부족하거나 잘못된 부분 그리고 질문 있으시면 언제든 댓글 부탁드려요! 감사합니다!👦🏻👋🏻

    728x90
    반응형

    '오늘의 Swift 상식' 카테고리의 다른 글

    QR code - Scan!  (0) 2021.09.21
    QR Code - 만들기편!  (0) 2021.09.15
    Protocol 2편 (Delegation, Extension, 상속, 합성)  (0) 2021.08.25
    Protocol 1편 (Protocol 정의 방법)  (0) 2021.08.16
    Class의 상속  (0) 2021.08.15

    댓글

Designed by Tistory.