[Swift]状態を共有して変化を伝播させるサンプル~didSetなど~


異なるクラス間で状態を共有する方法。

いくつか方法はありますが、今回はdelegateを使います。



あと、共有すると、状態の変化も伝播させたいですよね。

didSetと組み合わせて、"変更"を伝播させてみましょう。



``` GameSample.swift


/**
*  Delegateを定義する
*/
protocol PlayerDelegate: class {
    func improveStatus(newLevel:Int)->Void
}


/**
*  コントローラー
*/
class FieldViewController:UIViewController {
    
    var player:Player!
    var enemy:Enemy!
    
    @IBOutlet weak var enemyAttackButton: UIButton!
    @IBOutlet weak var playerAttackButton: UIButton!
    
    
    override func viewDidLoad(){
        super.viewDidLoad()
        
        self.playerAttackButton.addTarget(self, action: "playerAttack", forControlEvents: .TouchUpInside)
        self.enemyAttackButton.addTarget(self, action: "enemyAttack", forControlEvents: .TouchUpInside)
        
        self.player = Player.instance
        
        self.player.status.level = 2
        
        self.enemy = Enemy()
    }
    
    func enemyAttack(){
        self.player.status.hp -= self.enemy.status.attack
    }
    
    func playerAttack(){
        self.enemy.status.hp -= self.player.status.attack
    }
    
}


/**
*  プレイヤーのステータスセット
*/
class PlayerStatus {
    
    var delegate:PlayerDelegate?
    
    var level:Int = 1 {
        didSet {
            /// 変更されたら、新しいレベルに会わせて能力値が向上する
            self.delegate?.improveStatus(self.level)
            println("-- change level at delegate --")
        }
    }
    
    private var hp:Int = 1 {
        didSet {
            println("-- change hp --")
            println(self.hp.description)
            if self.hp < 0 {
                self.isAlive = false
            }
        }
    }
    
    private var power:Int = 1
    private var defence:Int = 1
    private var skil:Skil = .None
    
    var attack:Int {
        get {
            return self.power + self.skil.rawValue
        }
    }
    
    enum Skil:Int {
        case Cold = 10
        case Fire = 20
        case None = 0
    }
    
    var isAlive:Bool = true {
        didSet {
            if self.isAlive == false {
                // "負けました."アラートを出してスタートに戻る
            }
        }
    }
}


class GameMaster:PlayerDelegate {
    
    
    var status:PlayerStatus!
    
    
    init(){
        self.status = PlayerStatus()
        self.status.delegate = self
        
        /// level 1 からスタート
        self.status.level = 1
    }
    
    
    /**
    Levelアップ時のロジックを書く
    */
    func improveStatus(newLevel: Int) {
        
        println("-- change level --")
        
        self.status.hp = 15 * newLevel
        self.status.power = 5 * newLevel
        self.status.defence = 5 * newLevel
        
        if newLevel > 15 {
            self.status.skil = .Cold
            return
        }
        if newLevel > 5 {
            self.status.skil = .Cold
        }
    }
    
    
    /// instance
    class var instance:GameMaster {
        struct i {
            static let instance = GameMaster()
        }
        return i.instance
    }
    
}


/**
*  プレイヤーオブジェクト
*/
class Player {
    
    var status:PlayerStatus!
    
    init(){
        /// GameMasterからStatusセットをもらう
        let master = GameMaster()
        self.status = master.status
        self.status.level = 1
    }
    
    /// instance
    class var instance:Player {
        struct i {
            static let instance = Player()
        }
        return i.instance
    }
}


/**
*  敵のオブジェクト
*/
class Enemy {
    
    /// 本当はEnemyStatusを用意すべき
    var status:PlayerStatus!
    
    init(){
        let master = GameMaster()
        self.status = master.status
        self.status.level = 1
    }
}



```