2017-06-28 122 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,而不是这些。