2012-05-17 39 views
10

我的應用程序的一部分包含一個照片瀏覽器,與Apple的Photos應用程序有點類似,具有初始視圖控制器以瀏覽照片縮略圖和點擊照片時顯示的詳細視圖。ALAssetsLibrary - 接收到ALAssetsLibraryChangedNotification後出現故障

我使用ALAssetsLibrary訪問照片,並將ALAsset URL的數組傳遞給我的詳細信息視圖控制器,以便您可以從一張照片滑動到另一張照片。

一切都很正常,直到我收到ALAssetsLibraryChangedNotification而從一張照片刷卡另一個(詳細信息視圖控制器),這通常會導致崩潰:

通知:資產的庫而改變//我自己的NSLog當 通知時

裝載資產... //我自己的NSLog時,我開始重裝資產 縮略圖瀏覽器

斷言失敗:(大小== bytesRead),功能 - [ALAssetRepresentation _imageData],文件/SourceCache/AssetsLibrary/MobileSlideShow-1373.58.1/Sources/ALAssetRepresentation.m, 管線224

的代碼的特定行它崩潰上,是在調用[currentRep元],如下所示:

- (void)someMethod { 
     NSURL *assetURL = [self.assetURLsArray objectAtIndex:index]; 
     ALAsset *currentAsset; 

     [self.assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) { 

      [self performSelectorInBackground:@selector(configureDetailViewForAsset:) withObject:asset]; 

      } failureBlock:^(NSError *error) { 
        NSLog(@"failed to retrieve asset: %@", error); 
     }]; 
} 

- (void)configureDetailViewForAsset:(ALAsset *)currentAsset { 
    ALAssetRepresentation *currentRep = [currentAsset defaultRepresentation]; 

    if (currentAsset != nil) { 
     // do some stuff 
    } 
    else { 
     NSLog(@"ERROR: currentAsset is nil"); 
    } 

    NSDictionary *metaDictionary; 
    if (currentRep != nil) { 
     metaDictionary = [currentRep metadata]; 

     // do some other stuff 
    } 
    else { 
     NSLog(@"ERROR: currentRep is nil"); 
    } 
} 

我明白,一旦收到通知時,它以無效和ALAsset對象ALAssetRepresentation任何引用...但我怎麼處理這種情況的地方無效正在嘗試訪問它的東西正好?

我試過設置一個布爾值,接收通知權當完全中止,防止[currentRep元]從曾經被稱爲,但即使沒有每次都能釣到它:

if (self.receivedLibraryChangeNotification) { 
    NSLog(@"received library change notification, need to abort"); 
} 
else { 
    metaDictionary = [currentRep metadata]; 
} 

是有什麼我可以做的?在這一點上,我幾乎準備放棄使用ALAssetsLibrary框架。

(注意,描述了同樣的問題,蘋果開發論壇這個懸而未決的主題:https://devforums.apple.com/message/604430

回答

6

看來問題就在這裏:

[self.assetsLibrary assetForURL:nextURL 

    resultBlock:^(ALAsset *asset) { 
     // You should do some stuff with asset at this scope 
     ALAssetRepresentation *currentRep = [asset defaultRepresentation]; 
     // Assume we have a property for that 
     self.assetRepresentationMetadata = [currentRep metadata]; 
     ... 
     // assume we have a method for that 
     [self updateAssetDetailsView]; 
    } 

    failureBlock:^(NSError *error) { 
     NSLog(@"failed to retrieve asset: %@", error); 
    }]; 

一旦你得到了用戶的資產,最好是通過向您的詳細信息控制器子視圖提供必要的數據或通過高速緩存供以後使用來複制資產信息。避免ALAsset失效麻煩會很有幫助。當發送通知ALAssetsLibraryChangedNotification時,您可能需要放棄詳細信息控制器並從頭開始查詢庫內容。

+1

我必須做更多的測試...但這可能有幫助。它沒有在我上面的代碼中顯示(因爲我想簡化它在這裏發佈),但[currentRep元數據]在後臺線程中被調用。我改變了它,而是像你所建議的那樣,在「assetForURL」resultBlock中檢索元數據字典,恰好在主線程中。它迄今沒有崩潰......也許ALAssetRepresentation的-metadata方法不是線程安全的? –

+0

這裏最重要的是,通過'assetForURL'獲取媒體需要時間。因此,在完成塊之外,您無法確定您已下載媒體... – voromax

+0

我更新了我的問題,以準確顯示我在後臺線程中如何調用「元數據」方法。基於你的回答,我已經改變了它,以便我首先檢索元數據字典,然後將它和資源都傳遞給我的configureDetailView方法。再次,我需要做更多的測試,但目前爲止這麼好... –