UIImageWriteToSavedPhotosAlbum选择器语法问题

8

我正在努力让UIImageWriteToSavedPhotosAlbum在Swift中工作。https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/index.html#//apple_ref/c/func/UIImageWriteToSavedPhotosAlbum

不幸的是,文档只有Objective-C版本。

以下是我的代码:

func saveImage()
{
  UIImageWriteToSavedPhotosAlbum(uiimage, self, "saveImageComplete:::", nil)
}

func saveImageComplete(image:UIImage,err:NSError,context:UnsafePointer<()>)
{
  loadLastPhotoIntoGalleryIcon()
}

但问题在于它会抛出一个未识别的选择器NSInvalidArgumentException:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: 'app.PhotoEditor<0x14a1e400> does not respond to selector 
saveImageComplete:::'

你能指导我语法哪里出错,并告诉我如何正确指定选择器吗? 据我所知,每个冒号(:)代表方法预期的一个参数,因为它有3个参数,所以我给了它3个冒号。

谢谢!


可能是重复问题:@selector() in Swift? - Caleb
如果您的方法是Objective-C方法,选择器将类似于“saveImageCompleteImage:err:context:”。您不能省略名称的任何部分。 - Caleb
1
是的,在Obj-C中你可以这样做,但你并没有。我想要指出的是,你的函数名称与选择器"saveImageComplete:::"不匹配,而更接近我建议的方法。换句话说,根据你为函数选择的名称来看,你正在使用的选择器是错误的。而且,这也是你得到的错误信息所告诉你的。 - Caleb
1
现在,如果您将其作为答案放置,我可以接受!saveImageCompleteimage:err:context:已经起作用了!我不知道Swift没有带有相同的参数规范逻辑。 - Aggressor
尝试将回调函数设为公共的。 - Zdeněk Topič
显示剩余3条评论
6个回答

14

以上的方法都不适用于Swift3。对于那些在Swift3语法上苦苦挣扎的人,请尝试以下方法:

操作:

@IBAction func saveToPhotos(_ sender: AnyObject) {

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

目标:

func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {

    if error == nil {
        let ac = UIAlertController(title: "Saved!", message: "Image saved to your photos.", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(ac, animated: true, completion: nil)
    } else {
        let ac = UIAlertController(title: "Save error", message: error?.localizedDescription, preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(ac, animated: true, completion: nil)
    }
}

请参考此链接以获得更多澄清信息: https://www.hackingwithswift.com/read/13/5/saving-to-the-ios-photo-library


6

这里是正确的UIImageWriteToSavedPhotosAlbum/selector代码:

func onYesClicked(action:Int){
    // i'm using optional image here just for example
    if let image = getImage() {
        UIImageWriteToSavedPhotosAlbum(
            image, self,
            Selector("image:didFinishSavingWithError:contextInfo:"),
            nil)
    }
}

func image(
    image: UIImage!,
    didFinishSavingWithError error:NSError!,
    contextInfo:UnsafePointer<Void>)
{
    // process success/failure here
}

这里是最新的语法,更新至2016年。
@IBAction func clickedSaveToUsersCameraRoll()
    {
    print("actually saving yourImage.image to the camera roll, 2016.")
    UIImageWriteToSavedPhotosAlbum(
        yourImage.image!, self,
        #selector(savedOK(_:didFinishSavingWithError:contextInfo:)),
        nil)
    }

func savedOK(
        image:UIImage!,
        didFinishSavingWithError error:NSError!,
        contextInfo:UnsafePointer<Void>)
    {
    print("Wrote photo ok")
    }

4

如果您的方法是Objective-C方法,选择器将类似于"saveImageCompleteImage:err:context:"。需要记住,在Objective-C中,参数是方法名称的一部分,因此"saveImageComplete:::"不能指定在Swift中可能被调用的saveImageComplete(image:UIImage,err:NSError,context:UnsafePointer<()>)方法。


这是正确的。我错误地认为使用“:”指定参数的逻辑来自Objc,但实际上需要改为方法的全名“saveImageComplete:err:context:”(您可以省略第一个参数)。混淆的原因就在于,Swift允许您在冒号后省略第一个参数,但其他参数必须在字符串中明确声明! - Aggressor

3

在Swift 4.x和5.0中:

UIImageWriteToSavedPhotosAlbum(imageToSave, self, #selector(saveImageComplete(image:err:context:)), nil)

不要忘记在声明中加上@objc装饰器:

@objc private func saveImageComplete(image:UIImage, err:NSError, context:UnsafeMutableRawPointer?) {
    
}

1
你可以通过调用一行代码来实现这个。
   UIImageWriteToSavedPhotosAlbum(imageToSave!,self,nil,nil)

0

尝试使用Swift 4.x+

class ImageSaver: NSObject {
    func writeToPhotoAlbum(image: UIImage) {
        UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveError), nil)
    }

    @objc func saveError(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        print("Save finished!")
    }
}

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