2016-09-02 10 views
6

मैं चाहता हूं कि उपयोगकर्ता मेरे ऐप पर जाएं और स्विफ्ट में प्रोग्रामेटिक रूप से बटन दबाए जाने के बाद ऐप का स्क्रीनशॉट लें। मुझे पता है कि UIGraphicsGetImageFromCurrentImageContext() एक स्क्रीनशॉट लेता है लेकिन मुझे पूरी स्क्रीन की एक तस्वीर नहीं चाहिए। मैं एक आयताकार पॉप अप करना चाहता हूं (एक फसल टूल की तरह) और उपयोगकर्ता स्क्रीन के केवल एक निश्चित भाग का स्क्रीनशॉट लेने के लिए आयत खींच और आकार बदल सकता है। मैं आयताकार को WKWebView पर जाना चाहता हूं और वेब दृश्य की एक तस्वीर फसल करना चाहता हूं।UIView के हिस्से का स्क्रीनशॉट कैसे लें?

उत्तर

16

मानक स्नैपशॉट तकनीक drawViewHierarchyInRect है। और एक छवि का हिस्सा पाने के लिए, आप CGImageCreateWithImageInRect का उपयोग कर सकते हैं।

इस प्रकार, स्विफ्ट 2 में:

extension UIView { 

    /// Create snapshot 
    /// 
    /// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted), 
    ///     return snapshot of the whole view. 
    /// 
    /// - returns: Returns `UIImage` of the specified portion of the view. 

    func snapshot(of rect: CGRect? = nil) -> UIImage? { 
     // snapshot entire view 

     UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, 0) 
     drawViewHierarchyInRect(bounds, afterScreenUpdates: true) 
     let wholeImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     // if no `rect` provided, return image of whole view 

     guard let rect = rect, let image = wholeImage else { return wholeImage } 

     // otherwise, grab specified `rect` of image 

     let scale = image.scale 
     let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale) 
     guard let cgImage = CGImageCreateWithImageInRect(image.CGImage!, scaledRect) else { return nil } 
     return UIImage(CGImage: cgImage, scale: scale, orientation: .Up) 
    } 

} 

स्विफ्ट 3 में:

extension UIView { 

    /// Create snapshot 
    /// 
    /// - parameter rect: The `CGRect` of the portion of the view to return. If `nil` (or omitted), 
    ///     return snapshot of the whole view. 
    /// 
    /// - returns: Returns `UIImage` of the specified portion of the view. 

    func snapshot(of rect: CGRect? = nil) -> UIImage? { 
     // snapshot entire view 

     UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0) 
     drawHierarchy(in: bounds, afterScreenUpdates: true) 
     let wholeImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     // if no `rect` provided, return image of whole view 

     guard let image = wholeImage, let rect = rect else { return wholeImage } 

     // otherwise, grab specified `rect` of image 

     let scale = image.scale 
     let scaledRect = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale) 
     guard let cgImage = image.cgImage?.cropping(to: scaledRect) else { return nil } 
     return UIImage(cgImage: cgImage, scale: scale, orientation: .up) 
    } 

} 

और यह उपयोग करने के लिए, आप कर सकते हैं:

if let image = webView.snapshot(of: rect) { 
    // do something with `image` here 
} 
+1

महान काम हमेशा की तरह रोब। धन्यवाद। – damirstuhec

+0

बिल्कुल सही समाधान। एसओ पर अन्य लोग हैं लेकिन वे पूरी स्क्रीन पर कब्जा करते हैं। यह दोनों के लिए समाधान है। – Septronic

3

यह How to capture UIView to UIImage without loss of quality on retina display पर एक पहले से पूछा सवाल, लेकिन तेज में विस्तार करने के लिए (2.3) है:

extension UIView { 

    class func image(view: UIView) -> UIImage? { 
     UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0) 
     guard let ctx = UIGraphicsGetCurrentContext() else { 
      return nil 
     } 
     view.layer.renderInContext(ctx) 
     let img = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return img 
    } 

    func image() -> UIImage? { 
     return UIView.image(self) 
    } 
} 

तो आप कर सकते हैं या तो UIView.image(theView) साथ या देखने में ही let viewImage = self.view.image()

पूछकर एक दृश्य से एक छवि प्राप्त

ध्यान रखें कि यह मोटा है और शायद थ्रेड सुरक्षा आदि के लिए आगे की जरूरत है ....

संबंधित मुद्दे