2014-10-03 2 views
13

मैं आईओएस 8 में नए PHAssetChangeRequest कक्षा का उपयोग कर फोटो लाइब्रेरी में फ़ोटो का एक बड़ा बैच सहेजने की कोशिश कर रहा हूं। समस्या यह है कि यह तस्वीरों को सहेजने वाले डेमॉन की तरह दिखता है जो आम तौर पर तस्वीरों की एक बड़ी संख्या के साथ अप्रत्याशित रूप से दुर्घटनाग्रस्त हो रहा है (मैं 500 के बारे में कोशिश कर रहा हूँ)। किसी को भी इस सीमा के आसपास कैसे जाना है कोई विचार है? क्या यह डेमॉन में स्मृति उपयोग की समस्या है? यह परिवर्तन ब्लॉक पर एक टाइमआउट सीमा भी हो सकती है, क्योंकि नीचे दिए गए पहले 2 लॉग विवरणों में महत्वहीन अंतर नहीं है।नए फोटो ढांचे का उपयोग कर तस्वीरों का एक बड़ा बैच बचाओ?

assetsd डेमॉन पहले से ही इस उपयोग के मामले के लिए लेखांकन नहीं होना चाहिए के बाद से कुछ इस तरह काफी क्या सुपर जटिल मॉडल और नए तस्वीरें ढांचे में डिजाइन को संभालने में सक्षम होना चाहिए है? प्रलेखन नमूना स्वयं एक फोटो को बचाने की क्षमता दिखाता है।

यहाँ मेरी कोड नमूना है:

[[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 में तुल्यकालिक performChangesAndWait विधि की कोशिश की लेकिन यह भी एक ही समस्या है।

मैं सुझाव/विचारों के लिए खुला हूं, अटक गया हूँ! :(

+0

मुझे एक ही समस्या का सामना करना पड़ रहा है। मैं 4 छवियों को सहेजता हूं, और यह काम करता है, लेकिन अगर मैं मौजूदा छवियों को बदलने के लिए फिर से 4 छवियों को सहेजने का प्रयास करता हूं तो मुझे यह त्रुटि मिलती है। जब मैं समाधान के साथ आता हूं तो मैं आपको वापस ले जाऊंगा – Aggressor

+0

@Aggressor मैं वास्तव में फ़ोटो लाइब्रेरी में मौजूदा फ़ोटो को "प्रतिस्थापित" करने का कोई तरीका नहीं देखता हूं। मुझे लगता है कि आप उन्हें हटा सकते हैं और उन्हें फिर से जोड़ सकते हैं। –

+0

यह त्रुटि मेमोरी ओवरलोडिंग से प्रतीत होती है। मैंने UIImage के फ़ाइल आकार को कम कर दिया और यह समस्या को ठीक कर दिया। अगर आपको इसे देखने की ज़रूरत है तो मैं कोड पोस्ट कर सकता हूं। – Aggressor

उत्तर

-1

यह नहीं वास्तव में इस प्रश्न के लिए एक समाधान है, लेकिन यह एक समाधान है। तुम अब भी सफलतापूर्वक कैमरा रोल/फ़ोटो एप्लिकेशन पर फ़ाइलें सहेजने के लिए वर्ष ALAssetsLibrary उपयोग कर सकते हैं।

ALAssetsLibrary* lib = [[ALAssetsLibrary alloc] init]; 
[lib writeImageDataToSavedPhotosAlbum:imageData metadata:nil 
         completionBlock:^(NSURL *assetURL, NSError *error) 
{ 
    // start saving your next image 
}]; 

यह उन सभी तस्वीरों के माध्यम से लूपिंग करते समय एसेट्स लाइब्रेरी के एक उदाहरण का उपयोग करने की भी सिफारिश की जाती है, जिन्हें आप सहेजना चाहते हैं। आप संभवतः अगली छवि को सहेजने के लिए पहले छवि को बचाने के लिए भी इंतजार करना चाहते हैं।

आप फिर कनवर्ट कर सकते हैं यदि आवश्यक हो तो एक PHAsset के लिए परिसंपत्ति URL:

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

डिवाइस पर छवियों के एक बड़े बैच को प्रोसेस करना आपको एआरसी के आधुनिक दिनों में भी स्मृति प्रबंधन के बारे में बहुत सावधान रहना होगा। मेरे पास प्रक्रिया करने के लिए बड़ी संख्या में छवियां थीं (आकार बदलने के साथ 50+) और CGImageSourceCreateThumbnailAtIndex() as suggested by the answer here चुनने का अंत हो गया। यह इमेजियो का उपयोग करता है जो बहुत ही कुशल माना जाता है। केवल मुद्दा मैं शेष था कि किसी कारण से यह अभी भी याद करने के लिए पर लटका दिया जब तक कि मैं creationRequestForAssetFromImageAtFileURL के @autoreleasepool {} में मेरे लिए लूप लिपटे

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

बजाय है, मैं इस विधि का इस्तेमाल किया और यह सही काम किया 10 छवियों के लिए (कोड के इस हिस्से एक tableView:cellForRowAtIndexPath: में दोहराया है)

UIImage *thisImage=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@",serverInfo,self.URLs[indexPath.row]]]]]; 
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 
     PHAssetChangeRequest * assetReq = [PHAssetChangeRequest creationRequestForAssetFromImage:thisImage]; 
     NSLog(@"Added %ld assets",(long)indexPath.row); 
    } completionHandler:^(BOOL success, NSError *error) { 
     if (!success){ 
      NSLog(@"%@",error); 
     } 
}]; 
0

विचार छोटे बैच में यह कर रही है। PHPhotoLibrary::performChanges सभी एक साथ परिवर्तन अनुरोध सबमिट करते हैं, इसलिए यह भी समाप्त करने में सक्षम था, आप किसी प्रतिनिधि या ब्लॉक से प्रगति पर कोई भी अपडेट प्राप्त नहीं कर पाएंगे। 2017 डब्ल्यूडब्ल्यूडीसी सत्र "What's New in Photos APIs" नमूना ऐप "Creating Large Photo Libraries for Testing" के साथ आया था जो वास्तव में करता है। प्रत्येक performChanges में 10 छवियां सबमिट की गई हैं, और यूआई अपडेट 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() 
    } 
} 

generateImagesAndWriteToDisk ऊपर विधि आप क्या कभी अपने विधि 10 तस्वीर यूआरएल या तो का एक बैच वापस जाने के लिए के साथ प्रतिस्थापित करने की आवश्यकता है। मैं व्यक्तिगत रूप से रिकर्सन में लिखना पसंद नहीं करता हूं। कोड को आसानी से गैर-रिकर्सन शैली में बदला जा सकता है।

संबंधित मुद्दे