iOS 18 PHAsset URL из requestAVAsset

4e61325975baf9496c4bb48f20793321.jpg

Всем привет! Сегодня я с большой радостью буду обсуждать iOS 18. Наконец-то, уважаемые коллеги, пришло время и мне приобщиться к этой замечательной операционной системе — iOS 18 beta 4. Главной причиной моего участия стали наши продвинутые пользователи, которые уже активно тестируют iOS 18. Спасибо вам за это!

Сразу скажу, что я истинный любитель Apple и все, что с ней связано, вызывает у меня огромный интерес.

Стоит отметить, что iOS 18 beta 4 я буду сокращенно называть iOS 18. Также важно понимать, что методы и способы работы с ними могут измениться в релизной версии iOS 18.

В статье я поделюсь своим недавним опытом работы со следующими методами под iOS 18 beta 4, которые удивительным образом отличаются от предыдущих версий iOS.

Методы, которые я рассмотрю:

  • PHCachingImageManager().requestAVAsset()

  • FileManager.default.fileExists()

  • avAssetImageGenerator.copyCGImage(at:)

  • avAssetImageGenerator.generateCGImagesAsynchronously()

  • URL(filePath:)

Причина, по которой я выбрал именно эти методы, проста: отработанная технология, успешно работающая на iOS 15–17, дала сбой в них.

Все эти методы относятся к работе с медиафайлами пользователя и способам обращения к ним: path и URL. В статье я не буду подробно рассматривать детали работы с path и URL. Рекомендую ознакомиться с хорошей статьей на эту тему: …

Напомню, что:

Path:

  • Для медиа файлов на симуляторе:

    /Users/someUser/Library/Developer/CoreSimulator/Devices/062F31BC-B783-40E6-AD93-F5ABA5CF4636/data/Media/DCIM/100APPLE/IMG_0001.MOV
    
  • Для файлов приложения на симуляторе:

    /Users/someUser/Library/Developer/CoreSimulator/Devices/062F31BC-B783-40E6-AD93-F5ABA5CF4636/data/Containers/Data/Application/E3C0E780-2249-4EE5-BDAE-A1FE5BCEDCC4/Documents/Media/Videos/IMG_0001.MOV
    

На устройстве:

  • Для медиа файлов:

    file:///var/mobile/Media/DCIM/118APPLE/IMG_8018.MP4
    
  • Для файлов приложения:

    /var/mobile/Containers/Data/Application/07B67A27-4573-4A1E-9DA1-DB0E1437945D/Documents/Media/Videos/IMG_0001.MP4
    

Начнем с метода requestAVAsset

Метод requestAVAsset позволяет получить AVAsset для работы с медиа. Запрос вызывается следующим образом:

@available(iOS 8, *)
open func requestAVAsset(forVideo asset: PHAsset, options: PHVideoRequestOptions?, resultHandler: @escaping (AVAsset?, AVAudioMix?, [AnyHashable: Any]?) -> Void) -> PHImageRequestID

Пример использования:

PHCachingImageManager().requestAVAsset(
    forVideo: userPhoto.imageAsset,
    options: options
) { asset, _, _ in
    if let asset = asset as? AVURLAsset {
        print(asset.url.absoluteString) // выводит строку пути
        print(asset.url.relativePath) // выводит относительный путь
    }
}

В результате запроса после типа файла (.mov или .mp4) добавляется странная строка/суффикс, например, #YnBsa.... Я еще не выяснил, что это означает, но для симулятора и устройства значение идентично. Возможно, это связано с Apple ID.

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

Метод fileExists (atPath:)

Из документации:

open func fileExists(atPath path: String) -> Bool

Для проверки существования файла после выполнения каких-либо операций:

let relativePath = someUrl.relativePath
let absolutePath = someUrl.absoluteString
FileManager.default.fileExists(atPath: relativePath) // вернет true
FileManager.default.fileExists(atPath: absolutePath) // вернет false

В данном случае это объясняется тем, что fileExists(atPath: absolutePath) ищет файл с суффиксом #YnBsa....

Метод AVAssetImageGenerator.generateCGImagesAsynchronously

Из документации:

open func generateCGImagesAsynchronously(forTimes requestedTimes: [NSValue], completionHandler handler: @escaping AVAssetImageGeneratorCompletionHandler)

Предположим, мы используем строку, которую использовали для проверки fileExists, которая не содержит дополнительного элемента #YnBsa...:

let relativePath = someUrl.relativePath
let absolutePath = someUrl.absoluteString
var newURL = URL(filePath: relativePath)
let asset = AVAsset(url: newURL)
let avAssetImageGenerator = AVAssetImageGenerator(asset: asset)
avAssetImageGenerator.generateCGImagesAsynchronously(forTimes: Array([time, time])) { time, cgImage, _, result, error in
if let error {
print(error.localizedDescription) // получаем ошибку
return
}
}

В этом случае мы получаем ошибку: «Не удалось открыть файл «IMG_0001.MOV», так как у Вас нет разрешения на его просмотр.»

po error.localizedDescription

some : Error Domain=NSCocoaErrorDomain Code=257
"Не удалось открыть файл «IMG_0001.MOV», так как у Вас нет разрешения на его просмотр."
UserInfo={NSURL=file:// /var/mobile/Media/DCIM/118APPLE/IMG_0001.MOV, AVErrorFailedDependenciesKey=(
«assetProperty_AssetType"

Если использовать someUrl.absoluteString:

var newURL = URL(fileURLWithPath: someUrl.absoluteString)
let asset = AVAsset(url: newURL)
let avAssetImageGenerator = AVAssetImageGenerator(asset: asset)

То generateCGImagesAsynchronously будет работать как положено.

Итог

Таким образом, в iOS 18 мы получили новую защиту доступа к работе AVAssetImageGenerator, используя дополнительный ключ.

Где найти документацию?

Это вопрос времени.

А пока…

Любим, кодим, изучаем!

© Habrahabr.ru