Using completionSelector and completionTarget with

2019-04-13 14:52发布

I'm trying to figure out a way to have my iOS app save a screenshot to the Camera Roll and then pop up an alert to tell the user that the screenshot was saved successfully.

The only way I can think to do this would be with some form of an if/else loop (as you'll see in my pseudocode comments below), but I can't think of any syntax to work with the UIImageWriteToSavedPhotosAlbum function from UIKit. I've come across suggestions that say to use completionSelector and completionTarget on Apple's development site, but I don't really understand how to use them or what specific diction I should use for the completionSelector and completionTarget in my code. I'm relatively new to Swift.

Can someone explain how they work and how I can find the syntax for using them in my code?

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

4条回答
神经病院院长
2楼-- · 2019-04-13 15:41

Here is a working example for saving a screenshot of the current view in camera roll working in 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)
}

}

查看更多
仙女界的扛把子
3楼-- · 2019-04-13 15:49

@Dare's solution for checking error didn't work for me (Swift 2.0).

This slight modification did work:

func image(image: UIImage, didFinishSavingWithError: NSError?, contextInfo:UnsafePointer<Void>)       {
        if didFinishSavingWithError != nil
        {
            Helper.showNotifierInfo(DefaultTextFailed)
        }
        else
        {
            Helper.showNotifierInfo(DefaultTextSaved)
        }
    }
查看更多
我想做一个坏孩纸
4楼-- · 2019-04-13 15:50

Another example in swift 2.2

The key difference in this example is that the class that has the callback function has to extend from NSObject, (@objc may work too)

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
    }
}
查看更多
神经病院院长
5楼-- · 2019-04-13 15:54
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
   }

}
查看更多
登录 后发表回答