迁移到Swift 4.2后,我遇到了多个错误,其中一个很奇怪。这似乎是Xcode 10中的一个错误,但有没有可用的解决方法?
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, with: options)
} catch {
NSLog("Could not set audio session category")
}
****'setCategory(_:with :)'在Swift中不可用
如果您的目标是iOS 10+,只需转换到新的API并使用:
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
当您针对较旧的iOS版本(例如iOS 9)的应用尝试此操作时,您将收到setCategory(_:mode:options:)' is only available on iOS 10.0 or newer
错误。
这被报道为error in Apple's API并在Xcode 10.2中修复。对于较旧的Xcode版本(例如Xcode 10.1),我找到了一种解决方法。当您按照描述创建Objective-C帮助程序时,您仍然可以访问旧API,因为它仍然针对Objective-C公开。
如果您想要一个没有错误处理的快速内联修复,可以使用.perform()
方法调用Obj.-C API:
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)
}
如果您想要更多地控制错误,以下是如何立即执行此操作的步骤
Objective-C
中创建一个新的AudioSessionHelper.m
文件。当系统提示是否应创建桥接头文件时,单击是(如果您的项目中还没有)Header
文件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()
}
这是一个不美观的,并为您的项目添加了许多不必要的代码和文件,因此如果您迫切需要或必须立即在Xcode 10.1上使用Swift 4.2,请使用它。在所有其他情况下,最好使用Xcode 10.2。
我所做的就是打电话给setCategory(_:mode:options:)
。可以省略options:
参数,如果没有模式,则可以使用.default
模式。
这是Xcode 10的SDK中AVFoundation的一个问题。您可以通过编写调用旧API的Objective-C函数来解决它,因为它们仍然可以在Objective-C中使用。但是,如果您只针对iOS 10或更高版本,则可以使用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)")
}
资料来源:Swift Forum
该问题已在Xcode 10.2中得到解决。
对于带有iOS 9(及更早版本)的Xcode 10.1,唯一的其他建议解决方案来自Benno,并且依赖于Objective-C或perform(NSSelectorFromString("setCategory:error:"))
。不幸的是,给定的代码不能让你很好地处理错误,所以我想在使用Xcode 10.1时在单独的框架中引入一个简单地回退到Swift 4.1的解决方案(即使你的项目正在使用它也会工作)斯威夫特4.2)。
诀窍就是构建一个单独的框架(或lib)来使用旧版本的Swift(如4.1)来包装对setCategory(_:)
的调用。在此框架中,您只需要:
import AVFoundation
extension AVAudioSession {
@available (iOS 3.0, tvOS 9.0, watchOS 2.0, *)
@objc open func setCategorySwift(_ category: String) throws {
try setCategory(category)
}
}
(也可通过pod 'AVAudioSessionSetCategorySwift'
获得)
然后,回到你的Swift 4.2项目(最终是pod install
),你可以像setCategorySwift(AVAudioSession.Category.playback.rawValue)
一样使用它。使用try-catch的较长示例可能是:
import AVAudioSessionSetCategorySwift
let session = AVAudioSession.sharedInstance()
do {
if #available(iOS 10.0, *) {
try session.setCategory(AVAudioSession.Category.playback, mode: .default, options: [])
} else {
// Swift 4.2 workaround: https://github.com/coeur/AVAudioSessionSetCategorySwift
try session.setCategorySwift(AVAudioSession.Category.playback.rawValue)
}
try session.setActive(true)
} catch {
print("AVAudioSession.setCategory error: \(error)")
}