【问题标题】:Screenshot in Swift iOS?Swift iOS 中的屏幕截图?
【发布时间】:2014-10-16 03:58:34
【问题描述】:

如何通过代码(在 Swift 中)从屏幕上截取屏幕截图并保存? 我可以截屏并保存为图片吗?

我查看并看到了这段代码,但我不能使用它(我认为),因为它什么也没做。

var screen = UIScreen.mainScreen()
snapshotVieww = screen.snapshotViewAfterScreenUpdates(false)
UIGraphicsBeginImageContextWithOptions(screen.bounds.size, false, 0)
snapshotVieww.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
provino = UIImageView(image: image)

【问题讨论】:

  • 您在何处/何时调用该代码
  • 在“@IBAction func 屏幕(发件人:UIButton)”上
  • 试图绘制 snapshotVieww ...? N 描述一下 snapshotVieww?
  • 以及如何/何时显示新制作的图像视图?

标签: ios iphone image swift screenshot


【解决方案1】:

只需这几行代码即可获得视图的屏幕截图:(刚刚测试过)

  UIGraphicsBeginImageContextWithOptions(UIScreen.mainScreen().bounds.size, false, 0);
  self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
  var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();

  UIGraphicsEndImageContext();

  self.imgView.image = image;

【讨论】:

【解决方案2】:

使用 Swift 4 / iOS 10.3,您可以选择以下方法之一来解决您的问题。


1。截取视图控制器的视图

以下代码展示了如何截取屏幕截图并将其保存在设备相册中:

import UIKit

class ViewController: UIViewController {

    /* ... */

    @IBAction func screenshot(_ sender: UIBarButtonItem) {
        //Create the UIImage
        UIGraphicsBeginImageContextWithOptions(view.frame.size, true, 0)
        guard let context = UIGraphicsGetCurrentContext() else { return }
        view.layer.render(in: context)
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return }
        UIGraphicsEndImageContext()
        
        //Save it to the camera roll
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }

}

请注意,此代码的结果将是一个 .JPG 图像。另请注意,导航栏和状态栏不会出现在最终图像中。

从iOS 10开始,作为之前代码的替代,你可以使用下面的代码:

import UIKit

class ViewController: UIViewController {

    /* ... */

    @IBAction func screenshot(_ sender: UIBarButtonItem) {
        //Create the UIImage
        let renderer = UIGraphicsImageRenderer(size: view.frame.size)
        let image = renderer.image(actions: { context in
            view.layer.render(in: context.cgContext)
        })
        
        //Save it to the camera roll
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }

}

2。截取 iPhone 窗口的屏幕截图

如果要截取包含导航栏(但不包含状态栏)的截图,可以使用以下代码:

import UIKit

class ViewController: UIViewController {

    /* ... */

    @IBAction func screenshot(_ sender: UIBarButtonItem) {
        //Create the UIImage
        guard let layer = UIApplication.shared.keyWindow?.layer else { return }
        UIGraphicsBeginImageContextWithOptions(layer.frame.size, true, 0)
        guard let context = UIGraphicsGetCurrentContext() else { return }
        layer.render(in: context)
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return }
        UIGraphicsEndImageContext()
        
        //Save it to the camera roll
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }
 
}

从iOS 10开始,作为之前代码的替代,你可以使用下面的代码:

import UIKit

class ViewController: UIViewController {

    /* ... */

    @IBAction func screenshot(_ sender: UIBarButtonItem) {
        //Create the UIImage
        guard let layer = UIApplication.shared.keyWindow?.layer else { return }
        let renderer = UIGraphicsImageRenderer(size: layer.frame.size)
        let image = renderer.image(actions: { context in
            layer.render(in: context.cgContext)
        })
        
        //Save it to the camera roll
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }
     
}

提醒

从iOS 10开始,为了防止你的应用在调用screenshot(_:)方法时崩溃,你需要在项目的Info.plist文件中添加键NSPhotoLibraryUsageDescription

<key>NSPhotoLibraryUsageDescription</key>
<string>Some description to explain why access is required</string>

【讨论】:

  • 有没有办法提高拍摄图像的质量?
  • @Nicholas 此代码未考虑比例因子,因此它会在 Retina 显示器中创建像素化图像。替换为:UIGraphicsBeginImageContextWithOptions(view.frame.size, false, UIScreen.mainScreen().scale)
  • 如果要保存到相册,还需要Privacy - Photo Library Additions Usage Description
  • @ThihaAung 你有没有找到在屏幕截图中包含状态栏的方法?
  • 任何人都知道如何解决这个问题..仅在 iOS13 中面临问题。 stackoverflow.com/questions/58405106/…
【解决方案3】:

// 脸书或推特上分享的截图就是这样...

func shareButtonClickedToTwitter(){
UIGraphicsBeginImageContextWithOptions(CGSizeMake(320,320), false, 0)
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
self.view?.drawViewHierarchyInRect(CGRectMake(-30, -30, self.frame.size.width, self.frame.size.height), afterScreenUpdates: true)
var screenShot  = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.vc.showTWShare("I scored \(score) in Beanystalk can you do better? Available in App Store..", shareImage: screenShot)}


func shareButtonClickedToFaceboook() {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(320,320), false, 0)
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
self.view?.drawViewHierarchyInRect(CGRectMake(-30, -30, self.frame.size.width, self.frame.size.height), afterScreenUpdates: true)
var screenShot  = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.vc.showFbShare("I got \(score) Points whilst playing BeanyStalk! Can you beat me?..", shareImageF: screenShot)  }

// facebook分享函数。

    func showFbShare(messageFB: String , shareImageF: UIImage) {
  println(messageFB)
  if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook){
    var fbSheet = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
    fbSheet.completionHandler = {
      result in
      switch result {
      case SLComposeViewControllerResult.Cancelled:
        break
      case SLComposeViewControllerResult.Done:
        break
      }
    }
    fbSheet.addImage(shareImageF)
    fbSheet.setInitialText("\(messageFB) Click here to fun https://hereIsLink/")
    println(messageFB)
    self.presentViewController(fbSheet, animated: false, completion: {
    })
  }
  else {
    var alert = UIAlertController(title: "Accounts", message: "Please login to a facebook account to share.", preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alert, animated: true, completion: nil)
  }
}

// 推特分享功能

func showTWShare(message: String , shareImage: UIImage) {
println(message)
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter){
  var twSheet = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
  twSheet.completionHandler = {
    result in
    switch result {
    case SLComposeViewControllerResult.Cancelled:
      break
    case SLComposeViewControllerResult.Done:
      break
    }
  }
  twSheet.setInitialText("\(message) Click here 2 fun https://hereIsLink/") //The default text in the tweet
  twSheet.addImage(shareImage)
  println(message)
  self.presentViewController(twSheet, animated: false, completion: {
  })
}
else {
  var alert = UIAlertController(title: "Accounts", message: "Please login to a Twitter account to share.", preferredStyle: UIAlertControllerStyle.Alert)
  alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
  self.presentViewController(alert, animated: true, completion: nil)
} }

【讨论】:

    【解决方案4】:

    要截图,Imanou Petit 的回答非常好。我已经在一个扩展中处理了多个版本的 iOS 和 tvOS,并将其作为 pod (pod 'SwiftImageEffects') 提供。

    完整代码如下(来自https://github.com/Coeur/ImageEffects/blob/master/SwiftImageEffects/ImageEffects%2Bextensions.swift):

    extension UIView {
        /// Get a UIImage from the UIView
        /// - parameter opaque:
        /// A Boolean flag indicating whether the image is opaque. Specify true to ignore the alpha channel. Specify false to handle any partially transparent pixels.
        /// - parameter scale:
        /// The scale factor to apply to the image. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
        open func renderImage(opaque: Bool = false, scale: CGFloat = 0) -> UIImage {
            if #available(iOS 10.0, tvOS 10.0, *) {
                let format = UIGraphicsImageRendererFormat.default()
                format.opaque = opaque
                format.scale = scale
                return UIGraphicsImageRenderer(size: bounds.size, format: format).image { layer.render(in: $0.cgContext) }
            } else {
                // Fallback on earlier versions
                // The following methods will only return a 8-bit per channel context in the DeviceRGB color space.
                // Any new bitmap drawing code is encouraged to use UIGraphicsImageRenderer in lieu of this API.
                UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, scale)
                defer { UIGraphicsEndImageContext() }
                layer.render(in: UIGraphicsGetCurrentContext()!)
                return UIGraphicsGetImageFromCurrentImageContext()!
            }
        }
    }
    

    那么你可以简单的截图如下:

    func screenshot() {
        if let image = UIApplication.shared.keyWindow?.renderImage() {
            // saving will require a NSPhotoLibraryUsageDescription in your project's Info.plist
            UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
        }
    }
    

    【讨论】:

    • 这很酷。但是,如果我在屏幕上显示了任何弹出框或模态框,当我使用此代码时,我会在这些模态框周围出现奇怪的厚阴影,有什么办法可以解决吗?
    • @zaitsman 我不知道您的视图层次结构如何。尝试renderImage() 不同的窗口或不同的视图。如果你不能解决它,那么可以针对这些阴影询问一个特定的 Stack Overflow 问题。
    猜你喜欢
    • 1970-01-01
    • 2015-03-14
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多