2017-06-28 167 views
0

有沒有人有一個可以在Swift中實現的簡單狀態機的例子?我一直在google搜索,但只看到了很多第三方庫,這對我來說很不透明。我也看到很多高層次的討論,其中談論關於狀態機,但沒有顯示任何代碼。是否有人可以做一個簡單的計數器例子(如加1 /減1)?或者指給我一個?我知道這是一個很大的問題,但我的google-fu讓我失望。謝謝。State Machine In Swift 3

+0

查找Apple,Inc.通過Xcode文檔製作的示例項目。 –

+0

好吧,他們有這樣的事情:https://developer.apple.com/library/content/documentation/General/Conceptual/GameplayKit_Guide/StateMachine.html,但我想知道如何從頭開始創建狀態機,而不是使用一個預定義的。 –

+0

我建議你學習如何使用Xcode查找示例項目。 –

回答

1

Apple的GamePlayKit已將狀態機實現爲GKStateMachine。但GamePlayKit僅適用於iOS 9,因此我必須克隆GKStateMachine(和GKState)才能在我的某個應用中支持iOS 8。希望它會有所幫助。

EHStateMachine.swift

import Foundation 


class EHStateMachine { 
    private(set) var currentState: EHState? 
    private let states = NSMapTable<AnyObject, EHState>(keyOptions: [.objectPointerPersonality], 
                 valueOptions: [.strongMemory]) 

    // MARK: 

    init(states: [EHState]) { 
     guard states.count > 0 else { 
      fatalError("Can't create state machine with zero states.") 
     } 

     let tempStates = NSHashTable<AnyObject>(options: [.objectPointerPersonality]) 

     for state in states { 
      guard !tempStates.contains(type(of: state)) else { 
       fatalError("Duplicate instances of \(type(of: state)) found.") 
      } 

      tempStates.add(type(of: state)) 
     } 

     for state in states { 
      state.stateMachine = self 
      self.states.setObject(state, forKey: type(of: state)) 
     } 
    } 

    // MARK: 

    func canEnterState(_ stateClass: AnyClass) -> Bool { 
     if (states.object(forKey: stateClass) == nil) { 
      return false 
     } 

     if currentState == nil { 
      return true 
     } 

     return currentState!.isValidNextState(stateClass) 
    } 

    func enter(_ stateClass: AnyClass) -> Bool { 
     if !canEnterState(stateClass) { 
      return false 
     } 

     let previousState = currentState 
     let nextState = states.object(forKey: stateClass) 

     previousState?.willExit(to: nextState!) 
     currentState = nextState 
     currentState!.didEnter(from: previousState) 

     return true 
    } 

    func update(deltaTime seconds: TimeInterval) { 
     currentState?.update(deltaTime: seconds) 
    } 

    func state<T: EHState>(forClass stateClass: T.Type) -> T? { 
     return states.object(forKey: stateClass) as? T 
    } 
} 

EHState.swift

import Foundation 


class EHState { 

    weak var stateMachine: EHStateMachine? 

    // MARK: 

    func isValidNextState(_ stateClass: AnyClass) -> Bool { 
     return true 
    } 

    func didEnter(from previousState: EHState?) { 

    } 

    func willExit(to nextState: EHState) { 

    } 

    func update(deltaTime seconds: TimeInterval) { 

    } 
} 

如果定位到iOS 9,你應該使用GKStateMachineGKState,而不是這些。