wake-up-neo.com

AVAudioSession setCategory Verfügbarkeit in Swift 4.2

Nach der Migration auf Swift 4.2 erhalte ich mehrere Fehler, von denen einer seltsam ist. Es scheint ein Fehler in Xcode 1 zu sein, aber gibt es eine Problemumgehung?

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

**** 'setCategory (_: with :)' ist in Swift nicht verfügbar

16
Deepak Sharma

iOS 10+

Wenn Sie auf iOS 10 + abzielen, wechseln Sie einfach zur neuen API und verwenden Sie:

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

Ältere iOS-Versionen

Wenn Sie dies für eine App versuchen, die auf eine ältere iOS-Version abzielt (z. B. iOS 9) , wird ein setCategory(_:mode:options:)' is only available on iOS 10.0 or newer -Fehler angezeigt.

Dies wurde als Fehler in Apples API gemeldet und in Xcode 10.2 behoben. Für ältere Xcode-Versionen (zum Beispiel Xcode 10.1) habe ich eine Problemumgehung gefunden. Wenn Sie einen Objective-C-Helfer wie beschrieben erstellen, können Sie weiterhin auf die alte API zugreifen, da diese weiterhin für Objective-C verfügbar ist.

Problemumgehung 1: .perform () - Methode

Wenn Sie eine schnelle Inline-Korrektur ohne Fehlerbehandlung wünschen, können Sie die Obj.-C-API mit der .perform() -Methode aufrufen:

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)
}

Problemumgehung 2: Hilfsklassenmethode

Hier sind die Schritte, wie Sie dies jetzt tun können, wenn Sie mehr Kontrolle über Fehler haben möchten

  1. Erstellen Sie eine neue Objective-C - Datei in meinem Fall AudioSessionHelper.m. Wenn Sie gefragt werden, ob eine Bridging-Header-Datei erstellt werden soll, klicken Sie auf Ja (falls Sie noch keine in Ihrem Projekt haben)
  2. Erstelle eine neue Header Datei AudioSessionHelper.h
  3. Code eingeben
#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. Fügen Sie Ihre Hilfsklasse in die Bridging-Header-Datei ein
#import "AudioSessionHelper.h"
  1. Verwenden Sie es in Ihrem Swift Projekt
if #available(iOS 10.0, *) {
    try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
} else {
    try AudioSessionHelper.setAudioSession()
}

Dies ist nicht besonders schön und fügt Ihrem Projekt viele unnötige Codes und Dateien hinzu. Verwenden Sie diese also, wenn Sie dringend Swift 4.2 für Xcode 10.1 verwenden möchten oder müssen. In allen anderen Fällen sei besser dran mit Xcode 10.2.

31
Benno

Dies ist ein Problem mit AVFoundation in den SDKs von Xcode 10. Sie können dies umgehen, indem Sie eine Objective-C-Funktion schreiben, die die alte API aufruft, da sie in Objective-C weiterhin verfügbar ist. Wenn Sie jedoch nur auf iOS 10 oder höher abzielen, können Sie in Swift schreiben

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

Quelle: Swift Forum

1
Mehedi Hasan

Ich rufe setCategory(_:mode:options:) auf. Das options: Parameter kann weggelassen werden, und wenn Sie keinen Modus haben, können Sie einen Modus von .default.

1
matt

Das Problem wurde in Xcode 10.2 behoben.


Für Xcode 10.1 mit iOS 9 (und älter) ist die einzige andere vorgeschlagene Lösung von Benno und basiert auf Objective-C oder perform(NSSelectorFromString("setCategory:error:")). Leider lässt sich mit dem angegebenen Code nicht gut mit Fehlern umgehen. Daher möchte ich eine Lösung vorstellen, die darauf beruht, in einem separaten Framework auf Swift 4.1 zurückzugreifen, wenn Xcode 10.1 (und verwendet wird Es funktioniert auch, wenn Ihr Projekt Swift 4.2) verwendet.

Der Trick besteht einfach darin, ein separates Framework (oder eine separate Bibliothek) zu erstellen, um den Aufruf von setCategory(_:) mit einer älteren Version von Swift (wie 4.1) zu beenden müssen nur haben:

import AVFoundation

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

(auch verfügbar über pod 'AVAudioSessionSetCategorySwift' )

Dann, zurück zu Ihrem Swift 4.2 Projekt (und eventuell einem pod install), Können Sie es so einfach wie setCategorySwift(AVAudioSession.Category.playback.rawValue) verwenden. Ein längeres Beispiel mit try -fang, kann sein:

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