Swift 4.2中的AVAudioSession setCategory可用性

时间:2018-09-19 19:37:39

标签: swift xcode avaudiosession xcode10 swift4.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 :)'在Swift中不可用

4 个答案:

答案 0 :(得分:29)

iOS 10 +

如果您要定位 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:助手类方法

如果您想对错误进行更多控制,请按以下步骤操作

  1. 在我的情况下,Objective-C创建一个新的AudioSessionHelper.m文件。当系统提示您是否应创建桥接头文件时,单击(如果您的项目中还没有该文件)
  2. 创建一个新的Header文件AudioSessionHelper.h
  3. 插入代码
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
  1. 将您的帮助器类插入桥接头文件
[项目] -Bridging-Header.h
#import "AudioSessionHelper.h"
  1. 在您的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。

答案 1 :(得分:1)

这是Xcode 10的SDK中AVFoundation的问题。您可以通过编写调用旧API的Objective-C函数来解决该问题,因为它们仍可在Objective-C中使用。但是,如果您仅针对iOS 10或更高版本,则可以快速编写

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

答案 2 :(得分:1)

我要做的是打电话给setCategory(_:mode:options:)。可以省略options:参数,如果没有模式,则可以使用.default的模式。

答案 3 :(得分:0)

此问题已在Xcode 10.2中解决。


对于具有iOS 9(及更低版本)的Xcode 10.1,唯一建议的其他解决方案来自Benno,并且依赖Objective-C或perform(NSSelectorFromString("setCategory:error:"))。不幸的是,给定的代码不能让您很好地处理错误,因此我想介绍一种解决方案,该解决方案在使用Xcode 10.1时仅依赖于单独框架中的Swift 4.1(即使您的项目使用Swift 4.2)。

诀窍仅仅是使用早期版本的Swift(例如4.1)构建一个单独的框架(或lib),将调用包装为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)")
}