[ios] UIView를 이미지로 변환하는 방법

UIView를 이미지로 변환하고 내 앱에 저장하고 싶습니다. 누군가 뷰의 스크린 샷을 찍거나 이미지로 변환하는 방법과이를 앱 (카메라 롤이 아님)에 저장하는 가장 좋은 방법은 무엇입니까? 보기에 대한 코드는 다음과 같습니다.

var overView   = UIView(frame: CGRectMake(0, 0, self.view.frame.width/1.3, self.view.frame.height/1.3))
overView.center = CGPointMake(CGRectGetMidX(self.view.bounds),
CGRectGetMidY(self.view.bounds)-self.view.frame.height/16);
overView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(overView)
self.view.bringSubviewToFront(overView)



답변

확장 기능 UIView이 트릭을 수행해야합니다.

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}

Apple UIGraphicsBeginImageContext은 P3 색 영역을 도입하여 iOS 10을 시작하는 것을 권장하지 않습니다 . UIGraphicsBeginImageContextsRGB 및 32 비트 전용입니다. 그들은 UIGraphicsImageRenderer완전히 색상이 관리되고 블록 기반이며 PDF 및 이미지에 대한 하위 클래스가 있으며 컨텍스트 수명을 자동으로 관리 하는 새로운 API를 도입했습니다 . 확인 WWDC16 세션 (205) 자세한 내용은 (이미지 렌더링은 11시 50분 마크 주위에 시작)

모든 기기에서 작동하는지 확인하려면 #available이전 버전의 iOS 로의 폴 백과 함께 사용 하세요.

extension UIView {

    // Using a function since `var image` might conflict with an existing variable
    // (like on `UIImageView`)
    func asImage() -> UIImage {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContext(self.frame.size)
            self.layer.render(in:UIGraphicsGetCurrentContext()!)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return UIImage(cgImage: image!.cgImage!)
        }
    }
}


답변

당신은 확장을 사용할 수 있습니다

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}

여기에 신속한 3/4 버전이 있습니다.

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}


답변

에 의해 영상에 UIView의 변환 drawViewHierarchyInRect : afterScreenUpdates을 :여러 번 빠르게 renderInContext 이상

중요 참고 사항 : viewDidLoad 또는 viewWillAppear 에서이 함수를 호출하지 마십시오 . 뷰가 완전히 표시 /로드 된 후 뷰를 캡처하고 있는지 확인하십시오.

Obj C

     UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.opaque, 0.0f);
     [myView drawViewHierarchyInRect:myView.bounds afterScreenUpdates:NO];
     UIImage *snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

     myImageView.image =  snapshotImageFromMyView;

편집 된 이미지 사진 앨범 저장

     UIImageWriteToSavedPhotosAlbum(snapshotImageFromMyView, nil,nil, nil);

스위프트 3/4

    UIGraphicsBeginImageContextWithOptions(myView.bounds.size, myView.isOpaque, 0.0)
    myView.drawHierarchy(in: myView.bounds, afterScreenUpdates: false)
    let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    print(snapshotImageFromMyView)
    myImageView.image = snapshotImageFromMyView

확장자, iOS11, swift3 / 4로 매우 쉽게 일반화

extension UIImage{
    convenience init(view: UIView) {

    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    self.init(cgImage: (image?.cgImage)!)

  }
}


Use :
 //myView is completly loaded/visible , calling this code after only after viewDidAppear is call
 imgVV.image = UIImage.init(view: myView)
 // Simple image object
 let img =  UIImage.init(view: myView)


답변

iOS 10 :

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: (image?.cgImage)!)
    }
}


답변

iOS 10 및 Swift 3 기준 모범 사례

iOS 9 및 이전 버전을 계속 지원하면서
iOS 13, Xcode 11.1, Swift 5.1에서 계속 작동합니다.

extension UIView {

    func asImage() -> UIImage? {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
            defer { UIGraphicsEndImageContext() }
            guard let currentContext = UIGraphicsGetCurrentContext() else {
                return nil
            }
            self.layer.render(in: currentContext)
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
}

질문이 무엇을 의미하는지 잘 모르겠습니다.

카메라 롤이 아닌 앱에 저장하는 가장 좋은 방법은 무엇입니까?


답변

    UIGraphicsBeginImageContext(self.view.bounds.size);
    self.view.layer.renderInContext(UIGraphicsGetCurrentContext())
    var screenShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();


답변

예를 들어 크기보기가있는 경우 : 50 50 at 100,100. 다음을 사용하여 스크린 샷을 찍을 수 있습니다.

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), false, 0);
    self.view.drawViewHierarchyInRect(CGRectMake(-50,-5-,view.bounds.size.width,view.bounds.size.height), afterScreenUpdates: true)
    var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();