2016-09-15 4 views
0

Ich bin ein AudioManager in Swift 3 (bitte helfen Sie mir mit einem besseren Namen als „Audio-Manager“), die AVPlayer Wraps zu schreiben. Das Ziel ist es, einen Spieler Umgang mit Interrupts, Routenwechsel und Unterstützung von benutzerdefinierten Wiedergaberate, Sleep-Timer, Kommandozentrale, jetzt spielen Informationen etc. Da AVFoundation ist schwer ereignisgesteuert, mit KVO und NSNotification macht es Sinn, meine zu machen Projektereignis angetrieben. Ich habe ein Messaging-System integriert, bei dem verschiedene Teile der App Ereignisse entlang der Kette bis zum Stammknoten AudioManager senden. Also wollte ich eine Event-Repräsentation wie enum, weil das am meisten Sinn macht. Ich möchte jedoch, dass meine Ereignisse von z. RouteChange, BufferingEvent, InterruptionEvent usw. Also habe ich es endlich verschachtelte Aufzählungen mit arbeiten.Nested indirekte Aufzählungen in Swift

Ich schreibe ein Beispiel GUI, die dann Melodie in an Veranstaltungen von Audiomanager, statt mitNSNotification oder Verschlüsse zu verwenden.

editierte mit der Antwort zur Verfügung gestellt von @ andyvn22

enum AudioError: Error { 
    indirect case buffering(Buffering) 
    enum Buffering { 
     case unknown 
    } 

    indirect case playback(Playback) 
    enum Playback { 
     case failedToSetupAVAsset 
     case failedToSetupAVItem 
    } 

    init(_ buffering: Buffering) { 
     self = .buffering(buffering) 
    } 

    init(_ playback: Playback) { 
     self = .playback(playback) 
    } 
} 

enum Event { 
    case failure(AudioError) 

    init(_ error: AudioError) { 
     self = .failure(error) 
    } 

    init(_ bufferingError: AudioError.Buffering) { 
     self = .failure(AudioError.buffering(bufferingError)) 
    } 

    init(_ playbackError: AudioError.Playback) { 
     self = .failure(AudioError.playback(playbackError)) 
    } 

    indirect case buffering(Buffering) 
    enum Buffering { 
     case idle, started, finished 
    } 

    indirect case playback(Playback) 
    enum Playback { 
     case tick, wasPaused 
    } 

    indirect case route(RouteChange) 
    enum RouteChange { 
     case unavailable, available 
    } 

    indirect case interruption(Interruption) 
    enum Interruption { 
     case interrupted, interruptionEnded 
    } 
} 

Sie können das alles einfügen in einen Swift Spielplatz, und fügen Sie die handle Methoden und mit dem Beispiel Aufruf ruft unter:

func handle(_ error: AudioError.Buffering) { 
    handle(AudioError.buffering(error)) 
} 

func handle(_ error: AudioError) { 
    handle(Event.failure(error)) 
} 

func handle(_ event: Event) { 
    switch event { 
    case .failure(let errorType): 
     print("failure", terminator: " ") 
     switch errorType { 
     case .playback(let error): 
      print("playback", terminator: " ") 
      switch error { 
      case .failedToSetupAVAsset: 
       print("setupAVAsset") 
      case .failedToSetupAVItem: 
       print("setupAVItem") 
      } 
     case .buffering(let error): 
      print("buffering", terminator: " ") 
      switch error { 
      case .unknown: 
       print("unknown") 
      } 
     } 
    case .buffering(let buffering): 
     print("buffering", terminator: " ") 
     switch buffering { 
     case .idle: 
      print("idle") 
     case .started: 
      print("started") 
     case .finished: 
      print("finished") 
     } 
    case .playback(let playback): 
     print("playback", terminator: " ") 
     switch playback { 
     case .tick: 
      print("tick") 
     case .wasPaused: 
      print("wasPaused") 
     } 
    default: 
     print("unhandled case") 
    } 
} 

/* All these are equivalent */ 
handle(Event.failure(.buffering(.unknown))) 
handle(Event(.buffering(.unknown))) 
handle(Event(AudioError(.unknown))) 
handle(Event(.unknown)) 
handle(.unknown) 

ORIGINAL FRAGE
Es ist jedoch etwas mühsam, handle(Event(.buffering(.unknown))) zu schreiben, was bereits die Kurzversion von handle(Event.failure(.buffering(.unknown))) ist.

Meine Frage:
Ist es möglich, entweder AudioError.Buffering innerhalb eines Event mit case .failure mit nur einem inneren Fall zu schaffen oder AudioError.Playback?

die so etwas wie dies zu tun erlauben würde:

handle(Event(.unknown)) 

AudioError.Buffering und AudioError.Playback teilen keinen Fall mit dem gleichen Namen ...

Unter der Annahme,

Vielleicht habe ich einen coolen Teil von Swift 3 verpasst, was würde das erlauben?

Antwort

1

Ja - durch Überladen von Initialisierern können Sie die Initialisierung durch einen der Subtypen zulassen.Zum Beispiel:

enum AudioError: Error { 
    indirect case buffering(Buffering) 
    enum Buffering { 
     case unknown 
    } 

    indirect case playback(Playback) 
    enum Playback { 
     case failedToSetupAVAsset 
     case failedToSetupAVItem 
    } 

    init(_ buffering: Buffering) { 
     self = .buffering(buffering) 
    } 

    init(_ playback: Playback) { 
     self = .playback(playback) 
    } 
} 

let example = AudioError(.failedToSetupAVAsset) //this works... 
let other = AudioError(.unknown) //but so does this. 

Durch viele initializers Schaffung mag diese für jeden Subtyp, aber auf Event statt AudioError, können Sie nisten so viel wie Sie ohne Komplizierung Syntax möchten.

+0

sehr schön, ich musste noch ein paar mehr hinzufügen, um es zur Arbeit zu bringen, werde meine Fragen mit der Lösung aktualisiert, danke! – Sajjon

+0

Ich fügte zwei Einträge zu Event hinzu, einen für AudioError.Buffering und einen für AudioError.Playback, und ich fügte zwei Eingänge in AudioError hinzu. Ich habe auch zwei praktische 'func handle' erstellt, die eine sehr gute Syntax ermöglichen. – Sajjon

+0

Ist es möglich, den Code noch weiter zu aktualisieren? :) – Sajjon