xcode Swift 4.2 中的 AVAudioSession setCategory 可用性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52413107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 10:47:12  来源:igfitidea点击:

AVAudioSession setCategory availability in Swift 4.2

swiftxcodeavaudiosessionxcode10swift4.2

提问by Deepak Sharma

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?

迁移到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

**** 'setCategory(_:with:)' 在 Swift 中不可用

回答by Benno

iOS 10+

iOS 10+

If you are targeting iOS 10+, just transition to the new API and use:

如果您的目标是iOS 10+,只需过渡到新 API 并使用:

try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])


Older iOS versions

较旧的 iOS 版本

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 newerError.

当您针对针对较旧 iOS 版本(例如 iOS 9)的应用程序尝试此操作时,您将收到setCategory(_:mode:options:)' is only available on iOS 10.0 or newer错误消息。

This has been reported as an error in Apple's APIand 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.

这已在 Apple 的 API 中报告为错误,并在 Xcode 10.2 中修复。对于较旧的 Xcode 版本(例如 Xcode 10.1),我找到了一种解决方法。当您按照描述创建 Objective-C 帮助程序时,您仍然可以访问旧 API,因为它仍然为 Objective-C 公开。

Workaround 1: .perform() Method

解决方法 1:.perform() 方法

If you want a quick inline fix without the error handling, you can call the Obj.-C API with the .perform()method:

如果您想在没有错误处理的情况下进行快速内联修复,可以使用以下.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)
}

Workaround 2: Helper class method

解决方法 2:Helper 类方法

Here are the steps how to do it right now if you want some more control over errors

如果您想对错误进行更多控制,请立即执行以下步骤

  1. Create a new Objective-Cfile 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)
  2. Create a new Headerfile AudioSessionHelper.h
  3. Insert Code
  1. Objective-C在我的情况下创建一个新文件AudioSessionHelper.m。当提示是否应创建桥接头文件时,单击(如果您的项目中还没有)
  2. 创建一个新Header文件AudioSessionHelper.h
  3. 插入代码
音频会话助手.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. Insert your helper class into Bridging Header File
  1. 将您的助手类插入桥接头文件
[项目]-Bridging-Header.h
#import "AudioSessionHelper.h"
  1. Use it in your Swift project
  1. 在你的 Swift 项目中使用它
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.

这并不美观,并且为您的项目添加了许多不必要的代码和文件,因此如果您迫切需要或必须立即在 Xcode 10.1 上使用 Swift 4.2,请使用它。在所有其他情况下,您最好使用 Xcode 10.2。

回答by Mehedi Hasan

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

这是 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)")
}

Source: Swift Forum

来源:Swift 论坛

回答by matt

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.

我所做的就是调用setCategory(_:mode:options:). 该options:参数可以省略,如果你没有模式,你可以使用的模式.default

回答by C?ur

The issue has been resolved in Xcode 10.2.

该问题已在 Xcode 10.2 中解决。



For Xcode 10.1 with iOS 9 (and older), the only other proposed solution is from Benno and is to rely on either Objective-C or perform(NSSelectorFromString("setCategory:error:")). Unfortunately, the given code doesn't let you handle errors nicely, so I'd like to introduce a solution relying on simply falling back to Swift 4.1 in a separate framework when using Xcode 10.1 (and it will work even if your project is using Swift 4.2).

对于带有 iOS 9(及更早版本)的 Xcode 10.1,唯一提出的其他解决方案来自 Benno,并且依赖于 Objective-C 或perform(NSSelectorFromString("setCategory:error:")). 不幸的是,给定的代码不能让你很好地处理错误,所以我想介绍一个解决方案,它依赖于在使用 Xcode 10.1 时在单独的框架中简单地回退到 Swift 4.1(即使你的项目正在使用它也会工作斯威夫特 4.2)。

The trick is simply to build a separate framework (or lib) to wrap the call to setCategory(_:)using an older version of Swift (like 4.1). In this framework, you only need to have:

诀窍是构建一个单独的框架(或库)来包装对setCategory(_:)使用旧版本 Swift(如 4.1)的调用。在这个框架中,你只需要:

import AVFoundation

extension AVAudioSession {
    @available (iOS 3.0, tvOS 9.0, watchOS 2.0, *)
    @objc open func setCategorySwift(_ category: String) throws {
        try setCategory(category)
    }
}

(also available through pod 'AVAudioSessionSetCategorySwift')

(也可通过pod 'AVAudioSessionSetCategorySwift'

Then, back to your Swift 4.2 project (and a pod installeventually), you can use it as simply as setCategorySwift(AVAudioSession.Category.playback.rawValue). A longer example, with try-catch, may be:

然后,回到您的 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)")
}