Всем привет! Сегодня я с большой радостью буду обсуждать 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)
// выводит строку пути
// file:///var/mobile/Media/DCIM/118APPLE/IMG_0001.MP4#YnBsaXN0MDDRAQJfEBtSZWNvbW1lbmRlZEZvckltbWVyc2l2ZU1vZGUQAAgLKQAAAAAAAAEBAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAr
print(asset.url.relativePath)
// выводит относительный путь
// prints: /var/mobile/Media/DCIM/118APPLE/IMG_0001.MP4
}
}
В результате запроса после типа файла (.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, используя дополнительный ключ.
Где найти документацию?
Это вопрос времени.
А пока...
Любим, кодим, изучаем!