使用completionSelector和completionTarget与UIImageWriteToSavedPhotosAlbum一起

3
我正在尝试找到一种方法,让我的iOS应用程序将屏幕截图保存到相机胶卷中,然后弹出一个提示框告诉用户截图已成功保存。我唯一能想到的方法是使用某种形式的if/else循环(如下所示的伪代码注释),但我不知道该如何使用UIKit中的UIImageWriteToSavedPhotosAlbum函数。我在苹果开发网站上看到了建议,说要使用completionSelector和completionTarget,但我不太明白如何使用它们以及在我的代码中应使用哪些特定用语作为completionSelector和completionTarget。我对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)
}
5个回答

16
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
   }

}

你知道如何将这个更新到Swift 2.1吗? - swiftyboi
更新至 Swift 2.1 - Dare
如果 contextInfo 对象不是 nil,就能看到它是如何展开的,那就太好了。 - dumbledad

8

这是一个关于在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)
}

}


我一直不能让它对我起作用,有什么想法吗?UIImageWriteToSavedPhotosAlbum(imageToSave, #selector(PreviewViewController.image(_:didFinishSavingWithError:contextInfo:)), nil, nil) 并且定义为 @objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) - MichaelGofron

3

对于我来说,@Dare提供的检查错误的解决方案并没有起作用(Swift 2.0)。

这个轻微修改确实起作用了:

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

3

我从@David Rees的帖子中更新了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)

这应该是正确的答案。 - Vitor Venturin

1

另一个Swift 2.2的例子

这个例子的关键区别是,具有回调函数的类必须扩展自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
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接