此代码在iOS 7中运行良好,但在iOS 8.1中,位于“我的照片流”专辑中的所有资源都不在结果块中。 (未调用failureBlock。)常规专辑和共享专辑可以正常工作。
我尝试了接受的答案: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!");
}];
还有其他人看到这个问题吗?
答案 0 :(得分:30)
我遇到了同样的问题。此刻切换到Photos框架对我来说不是一个选项,但幸运的是我找到了一个解决方法。你可能会发现它很难看,我怀疑当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();
}
];
}
希望这有帮助。
答案 1 :(得分:2)
从iOS 8.0及更高版本开始,Apple建议使用Photos框架而不是Assets Library框架。
答案 2 :(得分:2)
我已经发现,在同一资产的writeImage toSavedPhotosAlbum成功块内使用assetForURL 检索资产将产生nil(大部分时间)的资产。 / p>
但是,在
等待1秒确实有效,而等待只有300毫秒没有。但是,这当然会因每种设备和情况而有所不同。
这并没有以令人满意的方式回答这个问题,但也许它可以帮助其他人解决潜在的问题。
答案 3 :(得分:1)
在iOS 8.1上使用iPad mini进行测试,您应该使用新的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 :(得分:-1)
在任何地方找不到任何答案之后,我为PHAsset创建了以下扩展,这在iOS 8.2中运行良好,尽管我认为它在理论上很慢。虽然之前的一条评论说这是在iOS8.2测试版上修复的,但是现在iOS 8.2发布后,这个bug仍然存在。
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
}
}
}