Surprise of the day: you can’t set AVAudioSession’s category in Swift 4.2 for iOS 9 and older

Today I was migrating a project to Swift 4.2 and encountered a quite bizarre issue. As it turns out, you can’t call the setCategory(_:) method on an instance of AVAudioSession in Swift 4.2 – the method was mistakenly marked as unavailable in this version of the language (and radars were filed). 

This can be a problem if your project targets iOS 9 or older, as the only alternative method setCategory(_:mode:options:) is available for iOS 10 and above. 

Objective-C to save your day!

Fortunately, the problem can easily be solved using Objective-C. You even have options here:

  • You can create an Objective-C category for AVAudioSession class and add a method that would call the setCategory:error: method, which is the objc counterpart of setCategory(_:). Just don’t forget to import the category in your bridging header.

OR

  • You can call setCategory:error using NSObject’s perform(_:with:with:) method. Like so:

This solution works because of the dynamic method resolution provided by the Objective-C runtime. NSSelectorFromString(_:) takes a method name as a string and returns a selector that was registered with the runtime system. This allows us to bypass the compile-time check for the method’s availability. And the perform(_:with:with:) method lets us send messages that aren’t determined until run-time.

To conclude, even though simple solutions for the issue were found, it still left me wondering how this silly mistake could make it to the production versions of Apple’s SDKs. 🤔

Leave a Reply

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