17

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

4 回答 4

36

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错误消息。

这已在 Apple 的 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:Helper 类方法

如果您想对错误进行更多控制,以下是立即执行此操作的步骤

  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。

于 2018-09-20T10:52:22.153 回答
1

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

资料来源:斯威夫特论坛

于 2018-09-20T03:57:26.237 回答
1

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

于 2018-09-20T04:01:23.247 回答
0

该问题已在 Xcode 10.2 中解决。


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

诀窍是简单地构建一个单独的框架(或 lib)来包装对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)
    }
}

(也可通过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)")
}
于 2018-10-19T10:54:53.527 回答