Using AVAsynchronousKeyValueLoading (and other similar APIs) in Swift

Apologies if this is something that's already possible or planned, but my initial searches turned up nothing. The AVAsynchronousKeyValueLoading protocol provides a method for loading certain values on AVFoundation objects via the loadValuesAsynchronously(forKeys:completionHandler:) method. Unfortunately, the keys parameter is of type [String], and so does not support any nice KeyPath Swiftiness. I'm curious if there is a plan for or a method to do either of the following:

  1. Turn a property name into a string so that typos could be caught at compile time. For example, calling this method with the key "availableMdiaCharacteristicsWithMediaSelectionOptions" on an AVAsset seems pretty gross even if the API is unlikely to change.

  2. Indicate in an Objective-C API that an NSString * parameter should (or array of NSStrings) should actually be treated as an (array of) KeyPath objects.

Are there technical limitations to either of these that make them undesirable to pursue? What is the "Swifty" way to use the AVAsynchronousKeyValueLoading API?

While it would be great if native Swift key paths were convertible to and from strings, for Objective-C objects you can use the #keyPath directive, introduced with SE-0062.

The expression #keyPath(AVAsset.duration) resolves to the string "duration" but is still checked by the compiler for typos (it fails if the property doesn't exist).

So you should be able to use the API like this:

asset.loadValuesAsynchronously(
    forKeys: [#keyPath(AVAsset.duration), #keyPath(AVAsset.creationDate)],
    completionHandler: ...)
2 Likes

Ah, for some reason I thought that KeyPaths had replaced the #keyPath directive. Thank you!