[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
    }
}