2016-04-27 10 views
1

Ich möchte alle Fotos, die im Gerät gespeichert sind, und speichern Sie sie in meiner App und dann schließlich (wenn Benutzer dies zulassen) Originale zu löschen.iOS - Holen Sie alle Fotos vom Gerät und speichern Sie sie in App

Das ist meine ganze Klasse I für diese Aufgabe erstellt:

class ImageAssetsManager: NSObject { 
    let imageManager = PHCachingImageManager() 

    func fetchAllImages() { 
    let options = PHFetchOptions() 
    options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue) 
    options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] 
    if #available(iOS 9.0, *) { 
     options.fetchLimit = 5 
    } else { 
     // Fallback on earlier versions 
    } 

    let imageAssets = PHAsset.fetchAssetsWithOptions(options) 
    print(imageAssets.count) 
    self.getAssets(imageAssets) 
    } 

    func getAssets(assets: PHFetchResult) { 
    var assetsToDelete: [PHAsset] = [] 

    assets.enumerateObjectsUsingBlock { (object, count, stop) in 
     if object is PHAsset { 
     let asset = object as! PHAsset 
     let imageSize = CGSize(width: asset.pixelWidth,height: asset.pixelHeight) 

     let options = PHImageRequestOptions() 
     options.deliveryMode = .FastFormat 
     options.synchronous = true 

     self.imageManager.requestImageForAsset(asset, targetSize: imageSize, contentMode: .AspectFill, options: options, resultHandler: { [weak self] 
      image, info in 

      self.addAssetToSync(image, info: info) 
      assetsToDelete.append(asset) 
      }) 
     } 
    } 
    self.deleteAssets(assetsToDelete) 
    } 

    func addAssetToSync(image: UIImage?, info: [NSObject : AnyObject]?) { 
    guard let image = image else { 
     return 
    } 

    guard let info = info else { 
     return 
    } 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { 
     let imageData = UIImageJPEGRepresentation(image, 0.95)! 
     let fileUrl = info["PHImageFileURLKey"] as! NSURL 

     dispatch_async(dispatch_get_main_queue(), { 
     let photoRootItem = DatabaseManager.sharedInstance.getPhotosRootItem() 
     let ssid = DatabaseManager.sharedInstance.getSsidInfoByName(ContentManager.sharedInstance.ssid) 
     let item = StorageManager.sharedInstance.createFile(imageData, name: fileUrl.absoluteString.fileNameWithoutPath(), parentFolder: photoRootItem!, ssid: ssid!) 
     }) 
    }) 
    } 

    func deleteAssets(assetsToDelete: [PHAsset]){ 
    PHPhotoLibrary.sharedPhotoLibrary().performChanges({ 
     PHAssetChangeRequest.deleteAssets(assetsToDelete) 
     }, completionHandler: { success, error in 
     guard let error = error else {return} 
    }) 
    } 
} 

Es funktioniert aber mein Problem ist, dass es nur für eine begrenzte Anzahl von Fotos funktioniert. Wenn ich es mit allen versuche, bekomme ich Speicherwarnungen und dann stürzt App ab. Ich weiß, warum es so ist. Ich weiß, dass mein Problem ist, dass ich alle Fotos in Erinnerung bekomme und es zu viel ist. Ich könnte Bilder mit diesem Abruflimit holen und es zur Schleife machen, aber ich bin nicht sicher, ob es beste Lösung ist.

Ich hatte gehofft, dass mit einigen Lösungsprozess wenige Fotos dann Speicher freigeben und immer wieder bis zum Ende. Aber diese Änderung wäre irgendwo in enumerateObjectsUsingBlock. Ich bin mir nicht sicher, ob es hilft, aber ich brauche nicht einmal ein Image. Ich muss nur die Image-Datei vom Gerätepfad in meinen App-Sandbox-Pfad kopieren.

Was ist die beste Lösung dafür? Wie vermeidet man Speicherwarnungen und -lecks? Danke

+0

Haben Sie eine Lösung? Ich stehe vor demselben Problem. –

Antwort

0

Ändern Sie Ihre dispatch_async Anrufe zu dispatch_sync. Dann werden Sie die Fotos einzeln bearbeiten, während Sie durch enumerateObjectsUsingBlock gehen, anstatt zu versuchen, alle gleichzeitig zu verarbeiten.