将 completionSelector 和 completionTarget 与 UIImageWriteToSavedPhotosAlbum 一起使用

Using completionSelector and completionTarget with UIImageWriteToSavedPhotosAlbum

我正在尝试找出一种方法让我的 iOS 应用程序将屏幕截图保存到相机胶卷,然后弹出警报告诉用户屏幕截图已成功保存。

我能想到的唯一方法是使用某种形式的 if/else 循环(正如您将在下面的伪代码注释中看到的那样),但我想不出任何语法来使用 UIKit 中的 UIImageWriteToSavedPhotosAlbum 函数。我在 Apple 的开发网站上遇到了使用 completionSelector 和 completionTarget 的建议,但我真的不明白如何使用它们或者我应该对 completionSelectorcompletionTarget 使用什么具体的措辞我的代码。我对 Swift 比较陌生。

谁能解释一下它们的工作原理以及我如何找到在我的代码中使用它们的语法?

func screenshotMethod()
{
    UIGraphicsBeginImageContextWithOptions(HighchartsView.scrollView.contentSize, false, 0);
    view.layer.renderInContext(UIGraphicsGetCurrentContext())
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    //if saved to Camera Roll
    //            {
    //              confirmScreenshot()
    //            }
    //        
    //else 
    //        {
    //            exit code/stop 
    //        }


}


func confirmScreenshot()
{
    let alertController = UIAlertController(title: "Success", message: "This chart has been successfully saved to your Camera Roll.", preferredStyle: .Alert)
    let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
    alertController.addAction(defaultAction)

    presentViewController(alertController, animated: true, completion: nil)
}
import UIKit

class ViewController: UIViewController {

   @IBAction func buttonPressed(sender: AnyObject) {
      presentImagePickerController()
   }

}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

   func presentImagePickerController() {
      let imagePickerController = UIImagePickerController()
      imagePickerController.delegate = self
      imagePickerController.sourceType = .PhotoLibrary
      imagePickerController.allowsEditing = false

      presentViewController(imagePickerController, animated: true, completion: nil)
   }

   func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
      UIImageWriteToSavedPhotosAlbum(image, self, "image:didFinishSavingWithError:contextInfo:", nil)
   }

   func imagePickerControllerDidCancel(picker: UIImagePickerController) {
      self.dismissViewControllerAnimated(true, completion: nil)
   }

   func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) {
      guard error == nil else {
         //Error saving image
         return
      }
      //Image saved successfully
   }

}

@Dare 的错误检查解决方案对我不起作用 (Swift 2.0)。

这个微小的修改确实有效:

func image(image: UIImage, didFinishSavingWithError: NSError?, contextInfo:UnsafePointer<Void>)       {
        if didFinishSavingWithError != nil
        {
            Helper.showNotifierInfo(DefaultTextFailed)
        }
        else
        {
            Helper.showNotifierInfo(DefaultTextSaved)
        }
    }

swift2.2

中的另一个例子

这个例子中的主要区别是 class 具有回调函数 必须从 NSObject 扩展,(@objc 也可以工作)

func writeImage(){
    let responder = WriteImageToFileResponder()
    responder.addCompletion{ print("completed") }

    let image = UIImage(color: .redColor(), size: CGSize(width: 100, height: 100))!
    UIImageWriteToSavedPhotosAlbum(image, responder, #selector(WriteImageToFileResponder.image(_:didFinishSavingWithError:contextInfo:)), nil)
}

class WriteImageToFileResponder: NSObject {
    var completion: (() -> Void)?

    func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeMutablePointer<Void>) {
        print(error)
        completion?()

    }

    func addCompletion(completion: (() -> Void)? ) {
        self.completion = completion
    }
}

这是一个工作示例,用于在 SWIFT 3.0

中工作的相机胶卷中保存当前视图的屏幕截图
 @IBAction func saveScreenshot(_ sender: Any) {

    //Create the UIImage
    UIGraphicsBeginImageContextWithOptions(editorView.frame.size, false, UIScreen.main.scale)

    //  UIGraphicsBeginImageContext(myTextView.frame.size)
    editorView.layer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    UIImageWriteToSavedPhotosAlbum(image!, self, #selector(TextEditorViewController.image(_:didFinishSavingWithError:contextInfo:)), nil)

}

func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if let error = error {
    // we got back an error!
    let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
    ac.addAction(UIAlertAction(title: "OK", style: .default))
    present(ac, animated: true)
} else {
    let ac = UIAlertController(title: "Saved!", message: "Your image has been saved to your photos.", preferredStyle: .alert)
    ac.addAction(UIAlertAction(title: "OK", style: .default))
    present(ac, animated: true)
}

}

我从@David Rees post

更新了 Swift 5 版本
import Foundation
class WriteImageToFileResponder: NSObject {
    typealias WriteImageToFileResponderCompletion = ((UIImage?, Error?) -> Void)?
    var completion: WriteImageToFileResponderCompletion = nil
    
    override init() {
        super.init()
    }
    
    @objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if (completion != nil) {
            error == nil ? completion?(image, error) : completion?(nil, error)
            completion = nil
        }
    }
    func addCompletion(completion:WriteImageToFileResponderCompletion) {
        self.completion = completion
    }
}

使用

let responder = WriteImageToFileResponder()
responder.addCompletion { (image, error) in
// completion block
}
// pass your image that you want to write 
let previewImage = UIImage(named:"sample")
UIImageWriteToSavedPhotosAlbum(previewImage, responder, #selector(WriteImageToFileResponder.image(_:didFinishSavingWithError:contextInfo:)), nil)