Swift 4.2 中的 AVAudioSession setCategory 可用性
AVAudioSession setCategory availability in Swift 4.2
迁移到 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:)' is unavailable in Swift
这是 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
我做的就是打电话setCategory(_:mode:options:)
。 options:
参数可以省略,如果你没有模式,可以使用.default
的模式。
iOS10+
如果您的目标是 iOS 10+,只需过渡到新的 API 并使用:
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
旧 iOS 版本
当您针对 较旧 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.
公开
解决方法 1:.perform() 方法
如果您想要快速内联修复而不需要错误处理,您可以使用 .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)
}
解决方法 2:助手 class 方法
如果您想更好地控制错误,请按以下步骤立即执行此操作
- 在我的例子中创建一个新的
Objective-C
文件 AudioSessionHelper.m
。当系统提示是否应创建桥接头文件时,单击 是(如果您的项目中还没有)
- 新建
Header
文件 AudioSessionHelper.h
- 插入代码
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
- 将你的助手 class 插入桥接头文件
[项目]-桥接-Header.h
#import "AudioSessionHelper.h"
- 在您的 Swift 项目中使用它
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.
此问题已在 Xcode 10.2 中解决。
对于 Xcode 10.1 和 iOS 9(及更早),唯一提出的其他解决方案来自 Benno,并且依赖于 Objective-C 或 perform(NSSelectorFromString("setCategory:error:"))
。不幸的是,给定的代码不能很好地处理错误,所以我想介绍一个解决方案,它依赖于在使用 Xcode 10.1 时在单独的框架中简单地回退到 Swift 4.1(并且它即使您的项目使用 Swift 4.2).
也能正常工作
诀窍就是构建一个单独的框架(或库)来使用旧版本的 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)")
}
迁移到 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:)' is unavailable in Swift
这是 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
我做的就是打电话setCategory(_:mode:options:)
。 options:
参数可以省略,如果你没有模式,可以使用.default
的模式。
iOS10+
如果您的目标是 iOS 10+,只需过渡到新的 API 并使用:
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
旧 iOS 版本
当您针对 较旧 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.
公开解决方法 1:.perform() 方法
如果您想要快速内联修复而不需要错误处理,您可以使用 .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)
}
解决方法 2:助手 class 方法
如果您想更好地控制错误,请按以下步骤立即执行此操作
- 在我的例子中创建一个新的
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
- 将你的助手 class 插入桥接头文件
#import "AudioSessionHelper.h"
- 在您的 Swift 项目中使用它
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.
此问题已在 Xcode 10.2 中解决。
对于 Xcode 10.1 和 iOS 9(及更早),唯一提出的其他解决方案来自 Benno,并且依赖于 Objective-C 或 perform(NSSelectorFromString("setCategory:error:"))
。不幸的是,给定的代码不能很好地处理错误,所以我想介绍一个解决方案,它依赖于在使用 Xcode 10.1 时在单独的框架中简单地回退到 Swift 4.1(并且它即使您的项目使用 Swift 4.2).
诀窍就是构建一个单独的框架(或库)来使用旧版本的 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)")
}