Как получить 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)
}
})
}
}
}