ALAssetsLibrary assetForURL: всегда возвращает ноль для фотографий в «My Photo Stream» в iOS 8.1




ios8.1 (4)

Этот код отлично работал в iOS 7, но в iOS 8.1 все активы, находящиеся в альбоме «My Photo Stream», равны нулю изнутри блока результатов. (The failureBlock не вызывается.) Обычные альбомы и общие альбомы работают нормально.

Я попробовал принятый ответ: Ошибка при попытке присвоить __block ALAsset изнутри 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!");
}];

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


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


После того, как я ничего не нашел для этого, я создал следующее расширение для 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
        }
    }
}

У меня такая же проблема. Переход на фреймворк фотографий в данный момент не является для меня вариантом, но, к счастью, я нашел обходное решение. Вы можете обнаружить, что это большой уродливый, и я подозреваю, что он может работать медленно, когда 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();
        }
  ];
}

Надеюсь это поможет.


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

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

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

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