Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/120.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用新的照片框架保存大量照片?_Ios_Ios8_Photosframework - Fatal编程技术网

Ios 使用新的照片框架保存大量照片?

Ios 使用新的照片框架保存大量照片?,ios,ios8,photosframework,Ios,Ios8,Photosframework,我正在尝试使用iOS 8中新的PHAssetChangeRequest类将一大批照片保存到照片库中。问题是,保存照片的守护进程本身似乎意外崩溃,照片数量适中(我尝试了大约500张)。有人知道如何绕过这个限制吗?守护进程本身是否存在内存使用问题?它也可能是更改块的超时限制,因为在下面的前两个日志语句之间有一个不小的间隙 assetsd守护进程不应该已经考虑到这个用例了吗,因为像这样的东西是新的Photos框架中的超级复杂模型和设计应该能够处理的吗?文档示例本身展示了保存照片的能力 以下是我的代码示

我正在尝试使用iOS 8中新的
PHAssetChangeRequest
类将一大批照片保存到照片库中。问题是,保存照片的守护进程本身似乎意外崩溃,照片数量适中(我尝试了大约500张)。有人知道如何绕过这个限制吗?守护进程本身是否存在内存使用问题?它也可能是更改块的超时限制,因为在下面的前两个日志语句之间有一个不小的间隙

assetsd
守护进程不应该已经考虑到这个用例了吗,因为像这样的东西是新的Photos框架中的超级复杂模型和设计应该能够处理的吗?文档示例本身展示了保存照片的能力

以下是我的代码示例:

[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    for (NSURL * url in fileURLs) {
        PHAssetChangeRequest * assetReq = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:url];
    }
    NSLog(@"Added %d assets",fileURLs.count);
} completionHandler:^(BOOL success, NSError *error) {
     if (!success){
         NSLog(@"%@",error);
     }
}];
这就是我的输出结果:

... Added 501 assets
... Connection to assetsd was interrupted or assetsd died
... Error Domain=NSCocoaErrorDomain Code=-1 "The operation couldn’t be completed. (Cocoa error -1.)
我甚至在
PHPhotoLibrary
中尝试了同步
performchange和wait
方法,但它也有同样的问题


我愿意接受建议/想法,我被卡住了!:(

这并不是这个问题的真正解决方案,但它是一种变通方法。您仍然可以使用旧的库将文件成功保存到“照相机卷/照片”应用程序

ALAssetsLibrary* lib = [[ALAssetsLibrary alloc] init];
[lib writeImageDataToSavedPhotosAlbum:imageData metadata:nil
                      completionBlock:^(NSURL *assetURL, NSError *error)
{
    // start saving your next image
}];
在循环浏览所有要保存的照片时,还建议使用AssetLibrary的单个实例。您可能还希望等待第一次图像保存完成后再开始保存下一张

然后,如果需要,您可以将生成的assetURL转换为PHAsset:

+ (PHFetchResult *)fetchAssetsWithALAssetURLs:(NSArray *)assetURLs
                                  options:(PHFetchOptions *)options

在设备上处理大量图像即使在ARC的现代时代,在内存管理方面也必须非常小心。我有大量图像要处理(50多个图像需要调整大小),最后选择了CGImageSourceCreateTumbnailatindex()。它使用的ImageIO应该是非常高效的。我唯一剩下的问题是,由于某种原因,它仍然会保留内存,除非我将for循环包装到@autoreleasepool{}

for (ALAsset *asset in assets) {
        @autoreleasepool {
            resizedImage = [self thumbnailForAsset:asset maxPixelSize:JPEG_MAX_DIMENSION];
        // do stuff here
    }
}

我使用了这个方法,而不是从ImageAtFileUrl创建AssetRequestForAssetFromImageAtFileUrl,它非常适合10幅图像(这部分代码在
表格视图中重复:cellForRowAtIndexPath:


这个想法是以小批量方式进行的。
PHPhotoLibrary::performChanges
一次性提交更改请求,因此即使它能够完成,您也无法从代理或块获得任何进度更新。2017年WWDC会话附带了一个示例应用程序“”正是这样。每个
performChanges
都提交了10个图像,UI更新来自
performChanges
的完成块,一个信号量阻塞线程,直到一批处理完成。我在这里发布重要的代码片段:

private func addPhotos() {
    let batchSize = min(photosToAdd, maxBatchSize)
    if batchSize <= 0 || !active {
        isAddingPhotos = false
        active = false
        return
    }

    workQueue.async {
        let fileURLs = self.generateImagesAndWriteToDisk(batchSize: batchSize)
        self.createPhotoLibraryAssets(with: fileURLs)

        DispatchQueue.main.async {
            self.addPhotos()
        }
    }
}

private func createPhotoLibraryAssets(with imageFileURLs: [URL]) {
    photoLibrarySemaphore.wait() // Wait for any ongoing photo library

    PHPhotoLibrary.shared().performChanges({
        let options = PHAssetResourceCreationOptions()
        options.shouldMoveFile = true
        for url in imageFileURLs {
            let creationRequest = PHAssetCreationRequest.forAsset()
            creationRequest.addResource(with: .photo, fileURL: url, options: options)
        }
    }) { (success, error) in
        if !success {
            print("Error saving asset to library:\(String(describing: error?.localizedDescription))")
        }
        self.photoLibrarySemaphore.signal()
    }
}
private func addPhotos(){
让batchSize=min(photosToAdd,maxBatchSize)

如果batchSize我遇到了类似的问题。我保存了4个图像,它可以工作,但是如果我再次尝试保存4个图像以替换现有的图像,我会遇到此错误。当我提出解决方案时,我会返回you@Aggressor我真的看不到“替换”的方法照片库中的现有照片。我想你可以删除并再次添加它们。这个错误似乎是由于内存过载。我减小了UIImage的文件大小,并解决了这个问题。如果你需要,我可以发布代码。不,我对减小文件大小的代码不感兴趣。我需要保存原始照片,而不是重新调整大小zed.我会想出一种不同的方法。我可以保证这是一个内存超出的错误。你有没有试过一次只做几次,然后清除缓存?比如把它分成10批,每次都清除缓存。你的DidReceiveMemory函数中有println吗?如果你全部运行500,内存函数会得到多少触发?能否在DidReceiveMemory警告中进行清除缓存调用?我遇到了同样的问题,并使用了一个OperationQueue,maxConcurrentOperationCount设置为1。您是否知道如何在使用
creationRequest.addResource时将创建日期和位置数据添加到正在创建的资产中
private func addPhotos() {
    let batchSize = min(photosToAdd, maxBatchSize)
    if batchSize <= 0 || !active {
        isAddingPhotos = false
        active = false
        return
    }

    workQueue.async {
        let fileURLs = self.generateImagesAndWriteToDisk(batchSize: batchSize)
        self.createPhotoLibraryAssets(with: fileURLs)

        DispatchQueue.main.async {
            self.addPhotos()
        }
    }
}

private func createPhotoLibraryAssets(with imageFileURLs: [URL]) {
    photoLibrarySemaphore.wait() // Wait for any ongoing photo library

    PHPhotoLibrary.shared().performChanges({
        let options = PHAssetResourceCreationOptions()
        options.shouldMoveFile = true
        for url in imageFileURLs {
            let creationRequest = PHAssetCreationRequest.forAsset()
            creationRequest.addResource(with: .photo, fileURL: url, options: options)
        }
    }) { (success, error) in
        if !success {
            print("Error saving asset to library:\(String(describing: error?.localizedDescription))")
        }
        self.photoLibrarySemaphore.signal()
    }
}