2016-09-15 3 views
0

Я пишу AudioManager in Swift 3 (пожалуйста, помогите мне с лучшим именем, чем «AudioManager»), который обертывает AVPlayer. Цель состоит в том, чтобы заставить игрока обрабатывать прерывания, изменять маршрут и поддерживать пользовательскую скорость воспроизведения, таймер сна, командный центр, теперь воспроизводить информацию и т. Д. Так как AVFoundation в значительной степени событие, приводимое в движение, с использованиеми NSNotification имеет смысл сделать мой проект также управляется. Я включил систему обмена сообщениями, где разные части приложения отправляют события вверх по цепочке, вплоть до корневого узла, AudioManager. Поэтому я хотел представить событие как enum, потому что это имеет смысл. Тем не менее, я хочу, чтобы мои события группировались, например. RouteChange, BufferingEvent, InterruptionEvent и т.д. Так что я, наконец, получил это работает, используя вложенными перечислений.Вложенные косвенные перечисления в Swift

Я пишу пример GUI, который затем может настроиться на события из AudioManager, вместо того, чтобы использовать NSNotification или закрытых участков.

Editted используя ответ предоставленного @ 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 
    } 
} 

Вы можете вставить все это в к Swift Playground и добавьте handle метод и называя это на примере вызовов ниже:

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 ВОПРОС
Однако немного утомительно написать handle(Event(.buffering(.unknown))), который уже является короткой версией handle(Event.failure(.buffering(.unknown))).

Мой вопрос:
Можно ли создать Event с case .failure, используя только внутренний корпус внутри либо AudioError.Buffering или AudioError.Playback?

Которые позволяют бы сделать что-то вроде этого:

handle(Event(.unknown)) 

Предполагая AudioError.Buffering и AudioError.Playback не разделяет дело с таким же названием ...

Возможно, я пропустил какую-то крутую часть Swift 3, что бы это разрешило?

ответ

1

Да - перегружая инициализаторы, вы можете разрешить инициализацию любым из подтипов.Например:

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. 

Создавая много инициализаторами любит их для каждого подтипа, но на Event, а не AudioError, вы можете гнездится столько, сколько вы хотите, не усложняя синтаксис.

+0

очень приятно, мне пришлось добавить еще несколько элементов, чтобы заставить его работать, обновит мои вопросы с помощью решения, спасибо! – Sajjon

+0

Я добавил два события к событию, одно для AudioError.Buffering и одно для AudioError.Playback, и я добавил два входа в AudioError. Я также создал два удобных 'func handle', которые обеспечивают очень хороший синтаксис. – Sajjon

+0

Возможно ли еще обновить код? :) – Sajjon

Смежные вопросы