개발/iOS

WKWebView 스크린샷

SKY STORY 2020. 5. 12. 15:34
반응형

WKWebView에서 화면 스크롤영역 전체 스크린샷을 구하는 방법을 알아보겠습니다.

iOS 11버전 부터 takeSnapshot이라는 함수를 제공하지만 실제로 정상적인 결과를 얻을 수 없습니다.

아래 클래스를 이용하면 보여지지 않는 스크롤 영역 전체의 스크린 샷을 구해 고화질로 저장할 수 있습니다.

주의 : 해당 함수는 웹페이지 로딩이 완료된 뒤 호출하셔야 합니다.

extension WKWebView{
    // 화면에 보여지는 부분만 스크린샷
    func screenshot(_ completionBlock: ((UIImage) -> Void)?) {
        if #available(iOS 11.0, *) {
            let config = WKSnapshotConfiguration()
            if #available(iOS 13.0, *) {
                config.afterScreenUpdates = false
            }
            config.rect = self.frame
            // iOS 11.0부터 takeSnapshot 함수를 사용할 수 있으나 스크롤영역 전체 스크린샷은 지원하지 않음(시뮬레이터는 가능)
            self.takeSnapshot(with: config, completionHandler: { image, error in
                if error != nil {
                    print("\(String(describing: error))")
                    return
                }
                guard let image = image else { return }
                completionBlock?(image)
            })
        } else {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, UIScreen.main.scale);
            self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
            guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return }
            UIGraphicsEndImageContext();
            completionBlock?(image)
        }
    }
    
    // 현재 페이지의 모든 컨텐츠 스크린샷
    func screenshot2(_ completionBlock: ((UIImage) -> Void)?) {
        let sv = self.scrollView
        let offset = sv.contentOffset
        let pageSize = sv.contentSize;
        let maxWidth = CGFloat(ceil(pageSize.width/sv.frame.size.width))
        let maxHeight = CGFloat(ceil(pageSize.height/sv.frame.size.height))
        for x in stride(from: 0, to: maxHeight, by: 1.0) {
            for y in stride(from: 0, to: maxWidth, by: 1.0) {
                sv.scrollRectToVisible(CGRect(x: sv.frame.size.width  * x,
                                              y: sv.frame.size.height * y,
                                              width:  sv.frame.size.width,
                                              height: sv.frame.size.height), animated: true)
                RunLoop.main.run(until: Date.init(timeIntervalSinceNow: 1.0))
            }
        }
        sv.setContentOffset(offset, animated: false)
        
        let prevOffset = sv.contentOffset
        let prevBounds = self.bounds
        let prevFrame = self.frame
        
        UIGraphicsBeginImageContext(pageSize)
        self.bounds = CGRect(x: self.bounds.origin.x, y: self.bounds.origin.y, width: pageSize.width, height: pageSize.height)
        self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: pageSize.width, height: pageSize.height)
        RunLoop.main.run(until: Date.init(timeIntervalSinceNow: 0.5))
        self.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        self.bounds = prevBounds
        self.frame = prevFrame
        sv.setContentOffset(prevOffset, animated: false)
        completionBlock?(image)
    }
}

 

☞ 웹뷰 화면 보여지는 부분만 스크린샷

webView.screenshot({(image) in
    print("complete")
})

 

☞ 웹뷰 화면 전체 스크린샷 (스크롤영역 전체)

webView.screenshot2({(image) in
    print("complete")
})

 

2020/05/12 - [iOS/Swift] - WKWebView 스크린샷

2020/05/12 - [iOS/Swift] - json 포멧 체크

2020/05/12 - [iOS/Swift] - Access Control (접근 제한자)

2020/05/12 - [iOS/Swift] - WKWebview에서 tel, email, mailto, sms, facetime 처리

 

반응형