ALAssetsLibrary在iOS 8.1中无法获取"My Photo Stream"中照片的URL,始终返回nil。

25

这段代码在iOS 7上运行良好,但在iOS 8.1中,“我的照片流”相册中的所有资产在结果块内都为null。(failureBlock未调用。)常规相册和共享相册工作得很好。

我尝试了这个答案:即,我持有对ALAssetsLibrary对象的引用,监听ALAssetsLibraryChangedNotification事件(顺便说一句,这个事件没有发生),我确保我的应用程序有权限访问照片,在wi-fi上,我可以在tableView中看到照片的缩略图。只是当我尝试使用assetForURL:加载它们时,它们总是为null。

// 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!");
}];

还有其他人遇到这个问题吗?

5个回答

30

我遇到了同样的问题。目前对我来说,转换到Photos框架不是一个选项,但幸运的是我找到了一个解决方法。你可能觉得它很难看,而且我怀疑当照片流中包含大量照片时它可能会工作缓慢,但总比没有好。

思路是枚举照片流资产组中的所有项目,并将所需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
虽然不是最理想的,但确实起到了作用,非常感谢!不过,我可能过于挑剔了,看起来 item.url 应该只是 url,对吧?而且我们可能需要调用一个成功的块,将 ALAsset 传递进去。再次感谢! - taber
奇怪,这边运行正常 - 你确定已经批准访问照片的权限了吗? - taber
那个解决方案对我也不起作用,因为在成功点#2中资产也是空的。 - Anas
1
@anas,在“成功点2”中,它到达了result变量,而不是asset - Andrew Simontsev
我们在哪里使用这个方法? - Sushil Sharma
显示剩余3条评论

2

从 iOS 8.0 开始,苹果建议使用 Photos 框架来替代 Assets Library 框架。

enter image description here


2
它并没有说我们“必须使用”Photos.framework。它只是告诉我们这是未来访问图片的方式。 - herzi

2
我注意到,在使用assetForURL尝试检索资源时,如果在写入图像到SavedPhotosAlbum成功的块内部尝试检索同一资源,大部分情况下会返回nil。
然而,在writeImage成功块执行完成后,稍后再使用assetForURL检索资源确实会返回正确的资源。
等待1秒可以解决问题,但只等待300毫秒则不能。但这当然对每个设备和情况都不同。
这并没有完全满意地回答问题,但也许能帮助其他人找出根本问题。

遇到了相同的问题。尽管写入已经成功解决,但在assetForURL请求中返回nil。对实际发生的事情感到好奇。 - rsiemens

1

在iOS 8.1上使用iPad mini测试,以下是使用新的照片框架的正确方法:

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

在任何地方都找不到答案后,我创建了以下扩展到PHAsset的内容,它在iOS 8.2上运行良好,尽管我认为它在理论上很慢。尽管之前的评论之一说这在iOS8.2 beta上已经修复了,但是现在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
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接