Как получить URL-адрес ALAsset от PHAsset?

Вы можете сделать это незаметно † используя недокументированные PHAsset.ALAssetURL собственность, но я ищу что-то задокументированное.


† В Objective-C это поможет

@interface PHAsset (Sneaky)

@property (nonatomic, readonly) NSURL *ALAssetURL;

@end

4 ответа

Решение

Создайте assetURL, используя локальный идентификатор PHAsset, Пример:PHAsset.localidentifier возвращается 91B1C271-C617-49CE-A074-E391BA7F843F/L0/001

Теперь возьмите 32 первых символа для создания assetURL, например:

assets-library://asset/asset.JPG?id=91B1C271-C617-49CE-A074-E391BA7F843F&ext=JPG

Вы можете изменить расширение JPG в зависимости от UTI актива (requestImageDataForAsset возвращает UTI), но в моем тестировании расширения assetURL, похоже, все равно игнорировались.

Я также хотел получить URL-адрес для ресурса. Тем не менее, я понял, что localIdentifier вместо этого можно сохранить и использовать для восстановления PHAsset,

PHAsset* asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil].firstObject;

Устаревшие URL-адреса активов можно преобразовать с помощью:

PHAsset* legacyAsset = [PHAsset fetchAssetsWithALAssetUrls:@[assetUrl] options:nil].firstObject;
NSString* convertedIdentifier = legacyAsset.localIdentifier;

(до того, как этот метод устарел...)

(Спасибо holtmann - localIdentifier спрятан в PHObject.)

Вот рабочий код, протестированный на iOS 11 как на симуляторе, так и на устройстве

PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
    [result enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        PHAsset *asset = (PHAsset *)obj;
        [asset requestContentEditingInputWithOptions:nil completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
            NSLog(@"URL:%@",  contentEditingInput.fullSizeImageURL.absoluteString);
            NSString* path = [contentEditingInput.fullSizeImageURL.absoluteString substringFromIndex:7];//screw all the crap of file://
            NSFileManager *fileManager = [NSFileManager defaultManager];
            BOOL isExist = [fileManager fileExistsAtPath:path];
            if (isExist)
                NSLog(@"oh yeah");
            else {
                NSLog(@"damn");
            }
        }];
    }];

Читайте дно!

ResultHandler для PHImageManager.requestImage возвращает 2 объекта: результат и информация

Вы можете получить исходное имя файла для PHAsset (например, IMG_1043.JPG), а также его полный путь в файловой системе с помощью:

let url = info?["PHImageFileURLKey"] as! URL

Это должно работать правильно, но по какой-то причине Apple облажалась. Таким образом, вы должны скопировать свое изображение в файл, затем получить доступ к нему, а затем удалить его.

PHImageFileURLKey можно использовать для получения исходного имени файла, но вы не можете получить к нему доступ. Вероятно, это связано с тем, что код в фоновом режиме может получить доступ к файлу, в то время как другие приложения могут его удалить.

Подумайте, сколько времени вы бы потратили на то, чтобы понять это с тех пор, как Apple облажалась, а не просто на документальное подтверждение. Может быть, это искренне, может быть, потому, что у них были разные разработчики, которые не понимали и не хотели работать. Здесь я работаю, а у Apple сколько сотен миллиардов в банке?

Да, извините, Apple, но я не согласен, когда у меня < 500 долларов и собственный капитал менее 1 года из 1700 подписчиков, платящих за 1 ТБ iCloud @ 10 долларов в месяц за работу в течение того же периода времени, с которого вы были восстановлены долг (2001 -> сейчас). Это был оригинальный iPhone, верно? Вы уверены, что обучаете их этим размерам данных, хотя не так, что масштабируемые месячные цены iCloud < 1% от среднего месячного дохода США!

Вот расширение PHAsset, написанное на Swift, которое извлекает URL.

extension PHAsset {

    func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
        if self.mediaType == .image {
            let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
            options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
                return true
            }
            self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
                completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
            })
        } else if self.mediaType == .video {
            let options: PHVideoRequestOptions = PHVideoRequestOptions()
            options.version = .original
            PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
                if let urlAsset = asset as? AVURLAsset {
                    let localVideoUrl: URL = urlAsset.url as URL
                    completionHandler(localVideoUrl)
                } else {
                    completionHandler(nil)
                }
            })
        }
    }
}
Другие вопросы по тегам