2011-06-06 10 views
5

मैं एलेसेट्स को एरे में स्टोर करने के लिए [एलासेट्स लाइब्रेरी एन्युमेरेट ग्रुप विथ टाइप्स:] का उपयोग कर रहा हूं। चूंकि यह एक असीमित ऑपरेशन है, इसलिए मुझे अपने काम को जारी रखने से पहले इसे खत्म करने की प्रतीक्षा करनी है।अलास्सेट्स लाइब्रेरी एन्युमरेट ग्रुप्सथथ टाइप्स: - थ्रेड सिंक्रनाइज़ेशन

मैंने Cocoa thread synchronisation when using [ALAssetsLibrary enumerateGroupsWithTypes:] पढ़ा और अनुशंसित NSConditionLock को आजमाया। हालांकि, ब्लॉक हमेशा मुख्य धागे में किए जाते हैं, इस प्रकार यदि मैं कंडीशनॉक का उपयोग करने का इंतजार करता हूं, तो मुख्य धागा अवरुद्ध हो जाता है और ब्लॉक निष्पादित नहीं होंगे -> मैं फंस गया हूं। मैंने एक नए धागे पर विधि loadAssets को चलाने का भी प्रयास किया, लेकिन फिर भी ब्लॉक मुख्य थ्रेड पर निष्पादित हो जाते हैं।

मुझे गणित खत्म होने के लिए वास्तव में प्रतीक्षा करने का कोई तरीका नहीं मिल रहा है। क्या मुख्य धागे की तुलना में ब्लॉक को किसी अन्य थ्रेड पर मजबूर करने का कोई तरीका है या मैं और कुछ भी कर सकता हूं?

- (void)loadAssets 
{ 
    assets = [NSMutableArray array]; 
    NSConditionLock *threadLock = [[NSConditionLock alloc] initWithCondition:THREADRUNNING]; 

    void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) 
    { 
     if(result != nil) 
     { 
      [assets addObject:result]; 
     } 
    }; 

    void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) 
    { 
     if(group != nil) 
     { 
      [group enumerateAssetsUsingBlock:assetEnumerator]; 
     } 

     [threadLock lock]; 
     [threadLock unlockWithCondition:THREADFINISHED]; 
    }; 

    void (^assetFailureBlock)(NSError *) = ^(NSError *error) 
    { 
     [threadLock lock]; 
     [threadLock unlockWithCondition:THREADFINISHED]; 
    }; 

    ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; 
    [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:assetGroupEnumerator failureBlock:assetFailureBlock]; 

    [threadLock lockWhenCondition:THREADFINISHED]; 
    [threadLock unlock]; 

    [assetsLibrary release]; 
    [threadLock release]; 
} 

उत्तर

1

आप अपने assetsLibrary वस्तु की हत्या कर रहे हैं इससे पहले कि यह वस्तुओं enumrate को समाप्त हो गया:

कोड यह रहा। इसे अपनी .h फ़ाइल पर ले जाएं और इसे डेलोक में रिलीज़ करें।

+0

मुझे नहीं लगता कि यह सही है। enumerateGroupsWithTypes लगभग निश्चित रूप से ऑब्जेक्ट को तब तक बनाए रखता है जब तक यह पूरा नहीं हो जाता है। यदि आप एनएसएलओजी का उपयोग करते हैं तो संपत्तियों को बनाए रखने के लिए पुस्तकालय, आप देखेंगे कि यह रिलीज के बाद भी 1 है। –

2

मैं जानता हूँ कि इस सूत्र शायद मर चुका है, लेकिन मैं इसे का जवाब दे रहा हूँ क्योंकि यह वह जगह है जहाँ मैं Googling

चाल जब तक गणन एक शून्य-समूह पैदावार अपनी पृष्ठभूमि धागा लॉक करने के लिए है से उतरा। यह श्रेणी इसका उपयोग करने का एक उदाहरण है, आप ALAssetsLibrary गणना विधि के ड्रॉप-इन प्रतिस्थापन के रूप में श्रेणी विधि का उपयोग कर सकते हैं।

@implementation ALAssetsLibrary (EEEConcurrency) 

- (NSUInteger)eee_enumerateGroupsLockedWithTypes:(ALAssetsGroupType)types 
             usingBlock:(ALAssetsLibraryGroupsEnumerationResultsBlock)enumerationBlock 
            failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock 
{ 
    NSAssert(![NSThread isMainThread], @"This would create a deadlock (main thread waiting for main thread to complete)"); 

    enum 
    { 
     EEEAssetsLibraryDone, 
     EEEAssetsLibraryBusy 
    }; 

    NSConditionLock *assetsLibraryConditionLock = [[NSConditionLock alloc] initWithCondition:EEEAssetsLibraryBusy]; 

    __block NSUInteger numberOfGroups = 0; 
    [self enumerateGroupsWithTypes:types 
         usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 
          enumerationBlock(group, stop); 
          if (group) numberOfGroups++; 
          if (!group || *stop) 
          { 
           [assetsLibraryConditionLock lock]; 
           [assetsLibraryConditionLock unlockWithCondition:EEEAssetsLibraryDone]; 
          } 
         } 
         failureBlock:^(NSError *error) { 
          failureBlock(error); 
          [assetsLibraryConditionLock lock]; 
          [assetsLibraryConditionLock unlockWithCondition:EEEAssetsLibraryDone]; 
         }]; 

    [assetsLibraryConditionLock lockWhenCondition:EEEAssetsLibraryDone]; 
    [assetsLibraryConditionLock unlock]; 

    return numberOfGroups; 
} 

@end 

डाउनलोड https://gist.github.com/epologee/8890692

+0

उप-वोटित! इसने मेरे विशिष्ट प्रश्न का उत्तर नहीं दिया हो सकता है, लेकिन इसने बड़े पैमाने पर सुराग दिया। मैं दस्तावेज़ों में चूक गया था कि जब गणना समाप्त होती है तो ब्लॉक को अंतिम कॉल एक शून्य समूह से गुजरता है। –

+0

धन्यवाद, यह कुछ ऐसा था जो मैंने पहली बार याद किया, मदद की खुशी! – epologee

0

पर श्रेणी इस कोड को हिस्सा आप के लिए काम करना चाहिए ->

ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init]; 
    dispatch_semaphore_t sema = dispatch_semaphore_create(0); 
    __block int numberOfGroups = 0; 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [assetsLib enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 
      if (group) { 
       numberOfGroups++; 
      } 
      else { 
       dispatch_semaphore_signal(sema); 
      } 
     } failureBlock:^(NSError *error) { 
      NSLog(@"enumerateGroupsWithTypes failure %@", [error localizedDescription]); 
      dispatch_semaphore_signal(sema); 
     }]; 
    }); 

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
    NSLog(@"number of groups is: %d", numGroups); 

हालांकि DISPATCH_TIME_FOREVER के बजाय आप समय अब ​​

से एक सेकंड बनाने के लिए चाहते हो सकता है
संबंधित मुद्दे