2012-05-17 32 views
10

Một phần của ứng dụng của tôi có trình duyệt ảnh, hơi giống với ứng dụng Ảnh của Apple, với bộ điều khiển chế độ xem ban đầu để duyệt ảnh thu nhỏ và chế độ xem chi tiết được hiển thị khi bạn nhấn vào ảnh.ALAssetsLibrary - crash sau khi nhận ALAssetsLibraryChangedNotification

Tôi đang sử dụng ALAssetsLibrary để truy cập ảnh và tôi chuyển một loạt URL ALAsset cho trình điều khiển chế độ xem chi tiết của tôi để bạn có thể vuốt từ một ảnh sang ảnh tiếp theo.

Tất cả mọi thứ hoạt động tốt, cho đến khi tôi nhận được một ALAssetsLibraryChangedNotification trong khi trượt từ một hình ảnh khác (trong bộ điều khiển xem chi tiết), mà thường dẫn đến một vụ tai nạn:

THÔNG BÁO: thư viện nội dung thay đổi // của tôi NSLog riêng cho khi thông báo xảy ra

tải tài sản ... // NSLog của riêng tôi khi tôi bắt đầu tải lại tài sản trong trình duyệt thumbnail

Assertion không thành công: (kích thước == bytesRead), chức năng - [ALAssetRepresentation _imageData], nộp /SourceCache/AssetsLibrary/MobileSlideShow-1373.58.1/Sources/ALAssetRepresentation.m, dòng 224.

Dòng cụ thể của mã nó bị treo trên, là trong gọi [currentRep metadata] như thể hiện ở đây:

- (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"); 
    } 
} 

tôi hiểu rằng một khi nhận được thông báo, nó làm mất hiệu lực bất kỳ tài liệu tham khảo để ALAsset và ALAssetRepresentation đối tượng ... nhưng làm thế nào tôi phải đối phó với tình hình nơi nó làm mất hiệu lực một cái gì đó đúng ở giữa cố gắng truy cập nó?

Tôi đã cố gắng thiết lập một BOOL, ngay khi nhận được thông báo hoàn toàn hủy bỏ và ngăn chặn [currentRep metadata] từ bao giờ được gọi, nhưng tất cả đều không bắt nó mỗi khi:

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

Is tôi có thể làm gì không? Tại thời điểm này, tôi gần như đã sẵn sàng từ bỏ việc sử dụng khung công tác ALAssetsLibrary.

(lưu ý chủ đề chưa được giải quyết này trên các diễn đàn dev của Apple mô tả cùng một vấn đề: https://devforums.apple.com/message/604430)

Trả lời

6

Có vẻ như vấn đề được quanh đây:

[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); 
    }]; 

Một khi bạn đã có tài sản sử dụng nó là tốt hơn để sao chép thông tin tài sản bằng cách cung cấp dữ liệu cần thiết cho các chi tiết của trình điều khiển phụ của bạn hoặc theo bộ nhớ đệm để sử dụng sau này. Nó có thể hữu ích để tránh những rắc rối về sự vô hiệu của ALAsset. Khi thông báo ALAssetsLibraryChangedNotification được gửi, bạn có thể cần phải loại bỏ bộ điều khiển chi tiết và truy vấn nội dung Thư viện ngay từ đầu.

+1

Tôi phải làm nhiều thử nghiệm hơn ... nhưng điều đó có thể đã giúp ích. Nó không được hiển thị trong mã của tôi ở trên (vì tôi muốn đơn giản hóa nó để đăng bài ở đây), nhưng [metadata siêu dữ liệu hiện tại] đang được gọi trong một chuỗi nền. Thay vào đó, tôi đã thay đổi để truy xuất từ ​​điển siêu dữ liệu bên trong resultBlock "assetForURL" như bạn đã đề xuất, điều này xảy ra trên chuỗi chính. Nó đã không bị rơi cho đến nay ... có lẽ phương pháp -metadata của ALAssetRepresentation không phải là chủ đề an toàn? –

+0

Điều quan trọng nhất ở đây là phải mất thời gian để lấy phương tiện với 'assetForURL'. Do đó, bên ngoài khối hoàn thành, bạn không thể chắc chắn mình đã tải xuống phương tiện ... – voromax

+0

Tôi đã cập nhật câu hỏi của mình để hiển thị chính xác cách tôi đã gọi phương thức "siêu dữ liệu" trong chuỗi nền. Dựa trên câu trả lời của bạn, tôi đã thay đổi nó để tôi truy xuất từ ​​điển siêu dữ liệu trước, sau đó chuyển cả từ đó và nội dung đó tới phương thức configureDetailView của tôi. Một lần nữa, tôi cần phải làm thử nghiệm nhiều hơn, nhưng cho đến nay rất tốt ... –

Các vấn đề liên quan