ALAssetsLibrary assetForURL: всегда возвращает ноль для фотографий в "My Photo Stream" в iOS 8.1
Этот код отлично работал в iOS 7, но в iOS 8.1 все активы, находящиеся в альбоме "My Photo Stream", равны нулю изнутри блока результатов. (Сбой отказа не вызывается.) Обычные альбомы и общие альбомы работают нормально.
Я попробовал принятый ответ: Ошибка при попытке присвоить __block ALAsset изнутри assetForURL: resultBlock:
То есть, я держу ссылку на объект ALAssetsLibrary, прислушиваясь к событию ALAssetsLibraryChangedNotification
(чего не происходит, но хорошо.) Я убедился, что у моего приложения есть разрешение на доступ к фотографиям, m на 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!");
}];
Кто-нибудь еще видит эту проблему?
Ответы
Ответ 1
У меня была та же проблема. Переход на фреймворк фотографий в данный момент не является для меня вариантом, но, к счастью, я нашел обходное решение. Вы можете обнаружить, что это большой уродливый, и я подозреваю, что он может работать медленно, когда Photo Stream содержит много фотографий, но это лучше, чем ничего.
Идея состоит в том, чтобы перечислить все элементы в группе активов 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();
}
];
}
Надеюсь, что это поможет.
Ответ 2
Из iOS 8.0 и более поздних версий вы должны использовать фреймворк "Фото" вместо структуры "Библиотеки ресурсов".
![enter image description here]()
Ответ 3
Протестировано iPad mini на iOS 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
}];
Ответ 4
Я сделал замечание о том, что попытка получить актив с помощью assetForURL внутри блока успеха writeImage toSavedPhotosAlbum для этого же актива приведет к активу nil (большую часть времени).
Однако извлечение актива с помощью ресурсаForURL через некоторое время после завершение выполнения блока writeImage завершает выполнение, дает правильный актив.
Ожидание в течение 1 секунды работало, ожидая только 300 мс. Но это, конечно, будет отличаться для каждого устройства и ситуации.
Это не отвечает на вопрос удовлетворительным образом, но, возможно, это помогает кому-то понять основную проблему.
Ответ 5
После того, как вы ничего не нашли, я создал следующее расширение для 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
}
}
}