Загрузка изображения из 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 * @"библиотека активов://актив/актив.JPG?id=4522DBD1-862C-42BE-AF7C-0D6C76CA7590&ext=JPG"

У кого-нибудь есть код для загрузки фотографий из «Мой фотопоток» или способ отключить его для отображения UIImagePicker?

Использование более старого API-интерфейса ALAssetsLibrary assetsForURL также не позволяет загрузить эти изображения.


person Werner Sharp    schedule 27.10.2014    source источник
comment
URL-адрес начинается с assets-library, поэтому для его получения следует использовать ALAssetsLibrary.   -  person gabbler    schedule 27.10.2014
comment
Как я уже сказал... Использование более старого API-интерфейса ALAssetsLibrary assetsForURL также не позволяет загрузить эти изображения. И в документах Apple для fetchAssetsWithALAssetURLs говорится, что каждый URL-адрес является URL-адресом актива, ранее извлеченным из объекта ALAsset.   -  person Werner Sharp    schedule 28.10.2014
comment
так вот вопрос как загрузить фото из My Photo Stream?   -  person gabbler    schedule 28.10.2014
comment
Конечно, или как на iOS8 вызвать средство выбора изображений, которое показывает все доступные фотографии и способ загрузки каждого типа. Что-то странное происходит с «моим фотопотоком».   -  person Werner Sharp    schedule 29.10.2014
comment
Вы когда-нибудь догадывались об этом?   -  person user3344977    schedule 16.12.2014
comment
Мы так и не разобрались. Если URL-адрес не может загрузить необработанный файл, мы возвращаемся и загружаем его как UIImage. Это не работает с нашим приложением для PNG с альфа-каналом, но отлично работает для JPG, который должен быть основным форматом в фотопотоке.   -  person Werner Sharp    schedule 17.12.2014
comment
Почти половина 2015 года, а это еще не решено? Удивительный!   -  person khose    schedule 06.04.2015
comment
У меня есть решение, проверьте это stackoverflow.com/questions/36003835/   -  person kb920    schedule 15.03.2016


Ответы (5)


Я думаю, вы можете попробовать это, чтобы получить альбом «мой фотопоток».

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.

person gabbler    schedule 29.10.2014
comment
Спасибо. Это позволяет выполнять итерацию по PHAssetCollection и получать список фотографий из My Photo Stream, но в каждом PHAsset нет URL-адресов, соответствующих тому, что UIImagePicker возвращает для выбранной фотографии в My Photo Stream. Есть ли замена UIImagePicker в iOS8? - person Werner Sharp; 29.10.2014
comment
Мой фотопоток должен отображаться в виде альбома при использовании UIImagePicker, UIImagePicker работает на iOS 8, вы можете использовать представление коллекции для отображения полученных изображений. Я предлагаю вам взглянуть на пример Photos от Apple. - person gabbler; 29.10.2014
comment
Пример Photos от Apple вообще не использует UIImagePicker. Проблема, с которой я столкнулся, заключается в том, что UIImagePicker (который показывает список My Photo Stream) позволяет выбирать этот тип фотографии, но URL-адрес, который он возвращает, бесполезен для фактической загрузки этого файла. Ни новый, ни старый API не работают. Это локальные фотографии на моем устройстве, так что это не значит, что изображение просто находится в облаке. - person Werner Sharp; 29.10.2014
comment
[info objectForkey:@UIImagePickerControllerOriginalImage] предоставит вам нужный UIImage, для чего вам нужен URL-адрес? - person gabbler; 30.10.2014

Не найдя нигде ответов на этот вопрос, я создал следующее расширение для 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
        }
    }
}
person Diego Rebosio    schedule 17.03.2015

Загрузка изображения с указанным URL-адресом из My Photo Stream с использованием ALAssetsLibrary обсуждается здесь:

ALAssetsLibrary assetsForURL: всегда возвращает ноль для фотографий в моем Фотопоток в iOS 8.1

Короче говоря, вместо использования assetsForURL вам нужно просмотреть все элементы в фотопотоке и сравнить их URL-адреса с вашими. Ссылка выше содержит пример кода.

Выглядит неуклюже, работает медленнее, чем assetsForURL, и не так просто определить, не найден ли какой-либо файл с указанным URL, но другого способа (кроме перехода на фреймворк Photos) я не нашел.

person Andrew Simontsev    schedule 20.11.2014

Для PHAsset я использую

[[PHImageManager defaultManager] requestImageForAsset:imageAsset
                                               targetSize:targetSize
                                              contentMode:PHImageContentModeAspectFit
                                                  options:options
                                            resultHandler:^(UIImage *img, NSDictionary *info)
{ // code for handle image }];

Я пытался использовать requestImageDataForAsset, но он возвращает nil для потоковых фотографий.

person Yuchao Zhou    schedule 09.10.2015

Работа для меня в 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
    })
}
person gerram    schedule 20.08.2015
comment
@Opticon хотел бы прокомментировать следующее: - не могу комментировать, поэтому спрашиваю так. Я реализовал это, но он всегда возвращает примерно 60x60. изображения, независимо от того, что я установил в targetSize. Вы знаете, как я могу восстановить исходную фотографию? Спасибо - person Craicerjack; 12.02.2016