iOS 18 PHAsset URL from requestAVAsset

Hello everyone! Today I will be very happy to discuss iOS 18. Finally, dear colleagues, the time has come for me to join this wonderful operating system — iOS 18 beta 4. The main reason for my participation was our advanced users who are already actively testing iOS 18. Thank you for this!

Let me say right away that I am a true Apple fan and everything connected with it arouses great interest in me.

It is worth noting that I will abbreviate iOS 18 beta 4 as iOS 18. It is also important to understand that the methods and ways of working with them may change in the release version of iOS 18.

In this article, I will share my recent experience with the following methods under iOS 18 beta 4, which are surprisingly different from previous versions of iOS.

The methods I will be looking at are:

  • PHCachingImageManager().requestAVAsset()

  • FileManager.default.fileExists()

  • avAssetImageGenerator.copyCGImage(at:)

  • avAssetImageGenerator.generateCGImagesAsynchronously()

  • URL(filePath:)

The reason I chose these methods is simple: the tried and tested technology that worked successfully on iOS 15-17 failed in them.

All these methods relate to working with user media files and ways to access them: path and URL. In this article, I will not go into details of working with path and URL. I recommend reading a good article on this topic:

Let me remind you that:

Path:

  • For media files on the simulator:

    /Users/someUser/Library/Developer/CoreSimulator/Devices/062F31BC-B783-40E6-AD93-F5ABA5CF4636/data/Media/DCIM/100APPLE/IMG_0001.MOV
    
  • For application files on the simulator:

    /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
    

On the device:

  • For media files:

    file:///var/mobile/Media/DCIM/118APPLE/IMG_8018.MP4
    
  • For application files:

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

Let's start with the requestAVAsset method

Method requestAVAsset allows you to get an AVAsset for working with media. The request is called as follows:

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

Example of use:

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

The query results in a strange string/suffix being added after the file type (.mov or .mp4), for example, #YnBsa.... I haven't figured out what this means yet, but it's the same for the simulator and the device. It might have something to do with the Apple ID.

Next we will have various transformations with the media file, and most likely we will save the path to the file in the media library so as not to store the media itself.

fileExists(atPath:) method

From the documentation:

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

To check if a file exists after performing any operations:

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

In this case, it is explained by the fact that fileExists(atPath: absolutePath) searches for file with suffix #YnBsa....

AVAssetImageGenerator.generateCGImagesAsynchronously method

From the documentation:

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

Let's say we use the string we used for checking fileExistswhich does not contain an additional element #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
}
}

In this case we get the error: “The file “IMG_0001.MOV” could not be opened because you do not have permission to view it.”

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"

If you use someUrl.absoluteString:

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

That generateCGImagesAsynchronously will work as expected.

Summary

So in iOS 18 we got new access protection for AVAssetImageGenerator work using an additional key.

Where can I find documentation?

It is the matter of time.

In the meantime…

We love, we code, we study!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *