Загрузка изображения из "My Photo Stream" с использованием URL-адреса результатов UIImagePicker и PHAsset на iOS8
Я обновил приложение с ios7 до ios8 и изо всех сил пытаюсь заставить UIImagePicker работать, загружая изображение из категории фотографий "Мой фотопоток". Реализация UIImagePicker является стандартной, и я получаю URL-адрес выбранной фотографии с помощью:
NSURL *url = [info objectForKey:@"UIImagePickerControllerReferenceURL"];
Затем я использую новые API IOS8 для загрузки этой фотографии:
PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];
Это не работает. Result.count равен нулю, и изображение не найдено. URL имеет другой UUID, чем если бы я выбрал фотографию из "Моментов" или "Фотопленка", но выглядит хорошо сформированным. (телефон работает 8.1):
url NSURL * @ "assets-library: //asset/asset.JPG? id = 4522DBD1-862C-42BE-AF7C-0D6C76CA7590 & ext = JPG"
У кого-нибудь есть код для загрузки фотографий из "My Photo Stream" или способ отключить его для отображения UIImagePicker?
При использовании более старого API-интерфейса assetAsURL ALAssetsLibrary эти изображения также не загружаются.
5 ответов
Я думаю, что вы можете попробовать это, чтобы получить альбом "my photo stream".
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumMyPhotoStream options:nil];
Фотографии в альбоме My Photo Stream загружаются в iCloud, и iCloud будет эффективно ими управлять, фотографии, сделанные в течение 30 дней, будут, и я думаю, что PHAsset или ALAssetLibrary имели дело с локально хранящимися активами. Вот тест, который я сделал на своем устройстве, я использовал imagePicker, чтобы получить URL-адрес фотографии из альбома в потоковом режиме, который был
"assets-library://asset/asset.JPG?id=60AE4E50-B835-47EB-B896-5974C21F8C9B&ext=JPG";
И используя PHAsset на той же фотографии, я получаю его localIdentifier:
"60AE4E50-B835-47EB-B896-5974C21F8C9B/L0/001"
Поэтому я думаю, что вы можете удалить идентификатор из URL и выяснить, какой локальный идентификатор актива содержит его, и тогда вы получите нужный PHAsset.
После того как я нигде не нашел ответов на этот вопрос, я создал следующее расширение для 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
}
}
}
Для PHAsset я использую
[[PHImageManager defaultManager] requestImageForAsset:imageAsset
targetSize:targetSize
contentMode:PHImageContentModeAspectFit
options:options
resultHandler:^(UIImage *img, NSDictionary *info)
{ // code for handle image }];
Я пытался использовать requestImageDataForAsset
, но он возвращает ноль для потоковых фотографий.
Загрузка изображения с указанным URL из My Photo Stream с использованием ALAssetsLibrary обсуждается здесь:
ALAssetsLibrary assetForURL: всегда возвращать ноль для фотографий в "My Photo Stream" в iOS 8.1
Короче говоря, вместо того, чтобы использовать assetForURL, вам придется перебирать все элементы в Фотопотоке и сравнивать их URL с вашими. Ссылка выше содержит пример кода.
Это выглядит неловко, работает медленнее, чем assetForURL, и не так просто определить, не найден ли какой-либо файл с указанным URL, но я не нашел другого способа сделать это (кроме перехода на платформу Photos).
Работа для меня в 8.0
import Photos
func imageFromAsset(nsurl: NSURL) {
let asset = PHAsset.fetchAssetsWithALAssetURLs([nsurl], options: nil).firstObject as! PHAsset
let targetSize = CGSizeMake(300, 300)
var options = PHImageRequestOptions()
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: PHImageContentMode.AspectFit, options: options, resultHandler: {
(result, info) in
// imageE - UIImageView on scene
self.imageE.image = result
})
}