2014-10-21 7 views
25

Этот код отлично работал в iOS 7, но в iOS 8.1 все активы, расположенные в альбоме «Мой фотопоток», равны нулю изнутри блока результатов. (The failureBlock не вызывается.) Обычные альбомы и общие альбомы работают нормально.ALAssetsLibrary assetForURL: всегда возвращает ноль для фотографий в «My Photo Stream» в iOS 8.1

Я попытался принятый ответ от: Error trying to assigning __block ALAsset from inside assetForURL:resultBlock:

То есть, я держу ссылку на объект ALAssetsLibrary, прислушиваясь к ALAssetsLibraryChangedNotification событие (которое не бывает кстати, ну да ладно.) Я сделал уверен, что у моего приложения есть разрешение на доступ к фотографиям, я нахожусь в wi-fi, я вижу, что миниатюры фотографий отлично подходят для моего стола. Просто когда я пытаюсь загрузить их с assetForURL:, они всегда ноль.

// example URL: assets-library://asset/asset.JPG?id=1ECB69B9-DC7A-45A7-B135-F43317D3412C&ext=JPG 
[self.library assetForURL:[NSURL URLWithString:url] resultBlock:^(ALAsset *asset) { 
    NSLog(@"Asset: %@", asset); // nil :(
} failureBlock:^(NSError *error) { 
    NSLog(@"Failure, wahhh!"); 
}]; 

Неужели кто-нибудь еще видит эту проблему?

ответ

30

У меня была такая же проблема. Переход на фреймворк фотографий в данный момент не является для меня вариантом, но, к счастью, я нашел обходное решение. Вы можете обнаружить, что это большой уродливый, и я подозреваю, что он может работать медленно, когда Photo Stream содержит много фотографий, но это лучше, чем ничего.

Идея состоит в том, чтобы перечислить все элементы в группе объектов «Фотопоток» и сравнить нужный URL-адрес с URL-адресом каждого элемента. К счастью, он все еще работает.

У меня есть метод, как эта (библиотека является ALAssetsLibrary собственности одного и тем же класса, возможно, потребуется инициализировать его внутри этого кода):

- (void)loadItem:(NSURL *)url withSuccessBlock:(void (^)(void))successBlock andFailureBlock:(void (^)(void))failureBlock { 

[library assetForURL:url 
     resultBlock:^(ALAsset *asset) 
     { 
      if (asset){ 
       ////////////////////////////////////////////////////// 
       // SUCCESS POINT #1 - asset is what we are looking for 
       ////////////////////////////////////////////////////// 
       successBlock(); 
      } 
      else { 
       // On iOS 8.1 [library assetForUrl] Photo Streams always returns nil. Try to obtain it in an alternative way 

       [library enumerateGroupsWithTypes:ALAssetsGroupPhotoStream 
             usingBlock:^(ALAssetsGroup *group, BOOL *stop) 
       { 
        [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { 
         if([result.defaultRepresentation.url isEqual:url]) 
         { 
          /////////////////////////////////////////////////////// 
          // SUCCESS POINT #2 - result is what we are looking for 
          /////////////////////////////////////////////////////// 
          successBlock(); 
          *stop = YES; 
         } 
        }]; 
       } 

            failureBlock:^(NSError *error) 
       { 
        NSLog(@"Error: Cannot load asset from photo stream - %@", [error localizedDescription]); 
        failureBlock(); 

       }]; 
      } 

     } 
     failureBlock:^(NSError *error) 
     { 
      NSLog(@"Error: Cannot load asset - %@", [error localizedDescription]); 
      failureBlock(); 
     } 
    ]; 
} 

Надеется, что это помогает.

+3

Хотя это не идеально, это действительно делает трюк, спасибо тонну! Не быть чрезмерно nitpicky, но похоже, что 'item.url' должен быть просто« url »правильным? И нам, вероятно, нужно будет вызвать блок успеха, который пройдет в ALAsset. Еще раз спасибо! – taber

+0

У меня такая же проблема как для Moment, так и для My Photo Stream, хотя решение выше не работает ... перечисляющие группы ничего не делают ... даже если я изменил ALAssetsGroupPhotoStream на ALAssetsGroupAll – AkademiksQc

+0

странно, это сработало здесь - вы уверены вы одобрили разрешение на фотографии? – taber

2

Из iOS 8.0 и более поздних версий вы должны использовать фреймворк «Фото» вместо структуры «Библиотека объектов».

enter image description here

+2

Он не говорит, что мы «должны использовать» Photos.framework. Просто скажите нам, что это способ доступа к изображениям в будущем. –

-1

После того, как я не нашел ответов на это, я создал следующее расширение для PHAsset, которое отлично работает с iOS 8.2, хотя я предполагаю, что он теоретически медленный. Несмотря на то, что в одном из предыдущих комментариев говорится, что это исправлено на бета-версии iOS8.2, ошибка теперь осталась для меня сейчас, когда iOS8.2 выпущен.

import Photos 
import UIKit 

extension PHAsset { 
    class func fetchAssetWithALAssetURL (alURL: NSURL) -> PHAsset? { 
     let phPhotoLibrary = PHPhotoLibrary.sharedPhotoLibrary() 
     let assetManager = PHImageManager() 
     var phAsset : PHAsset? 

     let optionsForFetch = PHFetchOptions() 
     optionsForFetch.includeHiddenAssets = true 

     var fetchResult = PHAsset.fetchAssetsWithALAssetURLs([alURL], options: optionsForFetch) 
     if fetchResult?.count > 0 { 
      return fetchResult[0] as? PHAsset 
     } else { 
      var str = alURL.absoluteString! 
      let startOfString = advance(find(str, "=")!, 1) 
      let endOfString = advance(startOfString, 36) 
      let range = Range<String.Index>(start:startOfString, end:endOfString) 
      let localIDFragment = str.substringWithRange(range) 
      let fetchResultForPhotostream = PHAssetCollection.fetchAssetCollectionsWithType(PHAssetCollectionType.Album, subtype: PHAssetCollectionSubtype.AlbumMyPhotoStream, options: nil) 
      if fetchResultForPhotostream?.count > 0 { 
       let photostream = fetchResultForPhotostream![0] as PHAssetCollection 
       let fetchResultForPhotostreamAssets = PHAsset.fetchAssetsInAssetCollection(photostream, options: optionsForFetch) 
       if fetchResultForPhotostreamAssets?.count >= 0 { 
        var stop : Bool = false 
        for var i = 0; i < fetchResultForPhotostreamAssets.count && !stop; i++ { 
         let phAssetBeingCompared = fetchResultForPhotostreamAssets[i] as PHAsset 
         if phAssetBeingCompared.localIdentifier.rangeOfString(localIDFragment, options: nil, range: nil, locale: nil) != nil { 
          phAsset = phAssetBeingCompared 
          stop = true 
         } 
        } 
        return phAsset 
       } 
      } 
      return nil 
     } 
    } 
} 
1

Испытан с IPad мини на прошивке 8.1, это то, как вы должны делать это с новым Photos Framework:

NSURL *url = /* your asset url from the old ALAsset library prior to iOS 8 */ 
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithALAssetURLs:@[url] 
                   options:nil]; 
assert(assets.count == 1); 
PHAsset *asset = assets.firstObject; 

[[PHImageManager defaultManager] requestImageForAsset:asset 
        targetSize:CGSizeMake(800, 800) // TODO: your target size 
        contentMode:PHImageContentModeDefault 
         options:nil 
       resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) 
{ 
    // Do whatever you want to the result 
}]; 
1

Я сделал замечание, что пытается получить актив, используя assetForURL внутри блок записи writeImage toSavedPhotosAlbum для этого же актива даст доход в размере nil (большую часть времени).

Однако получение актива с помощью assetForURL через некоторое время после блок успешного выполнения writeImage завершил выполнение, что дает правильный актив.

Ожидание 1 секунда работа была, в ожидании только 300 мс не делал. Но это, конечно, будет отличаться для каждого устройства и ситуации.

Это не отвечает на вопрос удовлетворительным образом, но, возможно, это помогает кому-то понять основную проблему.

+0

Испытывая ту же проблему. Несмотря на то, что запись успешно разрешила, она возвращает нуль в запросе assetForURL. Любопытно, что происходит на самом деле. – nudies