iOS实现相册和网络图片的存取

2020-01-20 12:48:05于海丽

保存 UIImage 到相册

UIKit

UIKit 中一个古老的方法,Objective-C 的形式

 

复制代码
void UIImageWriteToSavedPhotosAlbum(UIImage *image, id completionTarget, SEL completionSelector, void *contextInfo);

 

保存完成后,会调用 completionTarget 的 completionSelector。如果 completionTarget 不为空,completionTarget 必须实现以下方法

 

复制代码
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;

 

Objective-C 的写法


- (void)saveImage:(UIImage *)image {
  UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 
}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
  if (error) {
    // Fail
  } else {
    // Success
  }
}

Swift 的写法


func saveImage(_ image: UIImage) {
  UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: AnyObject) {
  if error == nil {
    // Success
  } else {
    // Fail
  }
}

Photos framework

iOS 8 开始,可以用 Photos framework。PHAssetChangeRequest 的类方法可以保存 UIImage

 

复制代码
class func creationRequestForAsset(from image: UIImage) -> Self

 

编辑相册需要在 PHPhotoLibrary 的闭包中进行,有两种方法

复制代码
func performChanges(_ changeBlock: @escaping () -> Void, completionHandler: ((Bool, Error?) -> Void)? = nil)

 

 

复制代码
func performChangesAndWait(_ changeBlock: @escaping () -> Void) throws

 

以上两种方法,分别是异步和同步执行。一般用第一种异步执行的方法,不会阻塞主线程。


func saveImage(_ image: UIImage) {
  PHPhotoLibrary.shared().performChanges({ 
    PHAssetChangeRequest.creationRequestForAsset(from: image)
  }, completionHandler: { (success, error) in
    // NOT on main thread
    if success {
      // Success
    } else if let error = error {
      // Handle error
    }
  })
}

编辑相册的闭包 changeBlock 和完成的闭包 completionHandler,是在 serial queue 中执行,不在主线程。需要更新 UI 的话,要切换到主线程中执行。

保存图片的 Data 到相册

如果有图片的数据(Data 或 NSData),可以用 Photos framework 的方法保存到相册。从 iOS 9 开始,可以使用 PHAssetCreationRequest 的方法

 

复制代码
func addResource(with type: PHAssetResourceType, data: Data, options: PHAssetResourceCreationOptions?)