web-dev-qa-db-ja.com

Swift 4.2でのAVAudioSession setCategoryの可用性

Swift 4.2に移行した後、複数のエラーが発生しています。そのうちの1つは奇妙です。 Xcode 1のバグのようですが、回避策はありますか?

do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord, with: options)
} catch {
    NSLog("Could not set audio session category")
}

**** 'setCategory(_:with :)'はSwiftでは使用できません

16
Deepak Sharma

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ヘルパーを作成する場合、Objective-Cにまだ公開されているため、古いAPIにアクセスできます。

回避策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_ファイルを作成します。ブリッジングヘッダーファイルを作成するかどうかを確認するメッセージが表示されたら、Yesをクリックします(プロジェクトにまだない場合)
  2. 新しいHeaderファイルを作成します_AudioSessionHelper.h_
  3. コードを挿入
_#ifndef AudioSessionHelper_h
#define AudioSessionHelper_h
#import <AVFoundation/AVFoundation.h>

@interface AudioSessionHelper: NSObject
+ (BOOL) setAudioSessionWithError:(NSError **) error;
@end

#endif /* AudioSessionHelper_h */
_
_#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. ヘルパークラスをブリッジングヘッダーファイルに挿入します
_#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を使用したほうが良いでしょう。

31
Benno

これは、Xcode 10のSDKのAVFoundationの問題です。古いAPIは引き続きObjective-Cで使用できるため、古いAPIを呼び出す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

1
Mehedi Hasan

私がすることは、setCategory(_:mode:options:)を呼び出すことです。 options:パラメーターは省略できます。モードがない場合は、.defaultのモードを使用できます。

1
matt

この問題は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など)を使用してsetCategory(_:)への呼び出しをラップするために、別のフレームワーク(またはlib)を構築することです。このフレームワークでは、持つ必要がある:

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)のように簡単に使用できます。 、 多分:

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)")
}
0
Cœur