読者です 読者をやめる 読者になる 読者になる

Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 691 - Closures, Extensions, Protocols, Delegation, and ScrollView 2

講義7をまったりと続けています。

Developing iOS 9 Apps with Swift - Free Course by Stanford on iTunes U

ViewControllerのライフサイクルを使ってARCのデモをするので、ViewControllerが作られた時に一度だけ呼ばれるメッセージviewDidLoad()でカウンターを増やして、消滅(ヒープから消し去る)する時に呼ばれるdeinitでカウンターを減らすステップを組み込んでコンソールにカウンターを表示させました。

これをベースに「string]」「weak」「unowned」のプロパティの挙動を見ていきます。

CalculatorBrainクラスにUrinaryOperationを加えるパブリックメソッドを用意します。

func addUnaryOperation(symbol: String, 
                       operation: (Double) -> Double) {
    operations[symbol] = Operation.UnaryOperation(operation)
}

これをViewControllerで呼ぶのですが、viewDidLoad()メソッドに加えます。

override func viewDidLoad() {
    super.viewDidLoad()
    calculatorCount += 1
    print("Loaded up a new Calculator (count = \(calculatorCount))")
    brain.addUnaryOperation("Z") {
        self.display.textColor = UIColor.redColor()
        return sqrt($0)
    }
}

クロージャーで指定している「self」の付いたプロパティが「strong」になりアプリが存在し続ける限りヒープに残ってしまうんです。

これをランして、「Calculate!」ボタンと「Back」ボタンを交互に押すと、次のようにViewControllerが次々と作成されてしまいます。

f:id:yataiblue:20160602162621j:plain

これが所謂メモリーリークという現象ですね。これを避けるために次のように「unowned」を使うやり方があります。

override func viewDidLoad() {
    super.viewDidLoad()
    calculatorCount += 1
    print("Loaded up a new Calculator (count = \(calculatorCount))")
    brain.addUnaryOperation("Z") { [ unowned me = self ] in
        me.display.textColor = UIColor.redColor()
        return sqrt($0)
    }
}

「weak」は基本的にオプショナル扱いになるので次のようにオプショナルチェインを使って実装します。

override func viewDidLoad() {
    super.viewDidLoad()
    calculatorCount += 1
    print("Loaded up a new Calculator (count = \(calculatorCount))")
    brain.addUnaryOperation("Z") { [ weak weakSelf = self ] in
        weakSelf?.display.textColor = UIColor.redColor()
        return sqrt($0)
    }
}

この2つの実装はどちらもメモリーリークがありません。

f:id:yataiblue:20160602163456j:plain

ということで今日はこれだけ。