After migrating to Swift 4.2, I am getting multiple errors, one of which is weird. It seems like a bug in Xcode 10, but is there a workaround available?
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, with: options)
} catch {
NSLog("Could not set audio session category")
}
**** 'setCategory(_:with:)' is unavailable in Swift
If you are targeting iOS 10+, just transition to the new API and use:
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
When you try this for an app targeting an older iOS version (for example iOS 9) you will get an setCategory(_:mode:options:)' is only available on iOS 10.0 or newer
Error.
This has been reported as an error in Apple's API and fixed in Xcode 10.2. For older Xcode versions (for example Xcode 10.1) there is a workaround I found. When you create an Objective-C helper as described you can still access the old API because it is still exposed for Objective-C.
If you want a quick inline fix without the error handling, you can call the Obj.-C API with the .perform()
method:
if #available(iOS 10.0, *) {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
} else {
// Set category with options (iOS 9+) setCategory(_:options:)
AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:withOptions:error:"), with: AVAudioSession.Category.playback, with: [])
// Set category without options (<= iOS 9) setCategory(_:)
AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:error:"), with: AVAudioSession.Category.playback)
}
Here are the steps how to do it right now if you want some more control over errors
Objective-C
file in my case AudioSessionHelper.m
. When prompted if a Bridging Header File should be created, click Yes (If you don't already have one in your project)Header
file AudioSessionHelper.h
#ifndef AudioSessionHelper_h
#define AudioSessionHelper_h
#import <AVFoundation/AVFoundation.h>
@interface AudioSessionHelper: NSObject
+ (BOOL) setAudioSessionWithError:(NSError **) error;
@end
#endif /* AudioSessionHelper_h */
AudioSessionHelper.m
#import "AudioSessionHelper.h"
#import <Foundation/Foundation.h>
@implementation AudioSessionHelper: NSObject
+ (BOOL) setAudioSessionWithError:(NSError **) error {
BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:error];
if (!success && error) {
return false;
} else {
return true;
}
}
@end
#import "AudioSessionHelper.h"
if #available(iOS 10.0, *) {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
} else {
try AudioSessionHelper.setAudioSession()
}
This is a not beautiful and adds lots of unnecessary code and files to your project, so use it if you urgently want or must use Swift 4.2 on Xcode 10.1 right now. In all other cases you would be better off using Xcode 10.2.
What I do is call setCategory(_:mode:options:)
. The options:
parameter may be omitted, and if you have no mode, you can use a mode of .default
.
This is an issue with AVFoundation in Xcode 10's SDKs. You can work around it by writing an Objective-C function that calls through to the old API, since they're still available in Objective-C. But if you're only targeting iOS 10 or later, you can write in swift
do{
if #available(iOS 10.0, *) {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: options)
} else {
//the following line is now "unavailable", hence there is no way to support iOS <10
//try AVAudioSession.sharedInstance().setCategory(.playAndRecord, with: options)
}
} catch let error {
print("Could not set audio session category: \(error.localizedDescription)")
}
Source: Swift Forum
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With