如果您想确保这些写入连续发生,您可以使用信号量等待图像完成,然后再开始下一次写入:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
for (UIImage *image in images) {
[library writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error) {
dispatch_semaphore_signal(semaphore); // signal when done
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // wait for signal before continuing
}
而且,由于您可能不想在此过程中阻塞主队列,因此您可能希望将整个事情分派到某个后台队列:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
for (UIImage *image in images) {
[library writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error) {
dispatch_semaphore_signal(semaphore); // signal when done
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // wait for signal before continuing
}
});
您也可以将这个writeImageToSavedPhotosAlbum 包装在一个自定义的NSOperation 中,直到完成块才发布isFinished,但这对我来说似乎有点矫枉过正。
话虽如此,我还是有点担心images 的这个数组,你在内存中同时保存了所有UIImage 对象。如果它们很大,或者如果你有很多图像,那可能会有问题。通常你会想要简单地维护一组图像名称,然后一次实例化一个图像,例如:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
for (NSString *path in imagePaths) {
@autoreleasepool {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
UIImage *image = [UIImage imageWithContentsOfFile:path];
[library writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error) {
dispatch_semaphore_signal(semaphore); // signal when done
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // wait for signal before continuing
}
}
});
人们通常应该警惕任何假定同时在内存中保存一组大型对象(如图像)的编码模式。
如果您需要经常访问这些图像,但又不想每次都从持久存储中重新检索,您可以使用NSCache 模式(例如,尝试从缓存中检索图像;如果找不到,从持久存储中检索并将其添加到缓存中;在内存压力下,清空缓存),这样您就可以享受将图像保存在内存中的性能优势,但可以优雅地处理图像缓存消耗过多内存的情况。