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

SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

Swift 2.0 で追加された defer について

defer

deferは、Swift 2.0 で新たに追加された構文です。
The Swift Programming Language: Statements
f:id:furuya02:20150823052955p:plain

deferの動作

deferを使用すると、スコープを抜ける際に実行する処理を記述することができます。
超簡単に例を示せば、次のようになります。

func f(){
    defer{
        print("2")
    }
    print("1")

}
// print "1"
// print "2"

deferを複数定義した場合L.I.F.O.で処理されます。

func f(){
    defer{
        print(“1”)
    }
    defer{
        print(“2”)
    }
   defer{
        print(“3”)
   }
}
// print "3"
// print "2"
// print "1"

利用場所

「絶対的有効!」となるような場面がちょっと思いつかなかったのですが、一応例として
仮ですが、下記のような処理があったとして・・・

func MyFunc(){
        
    // ストリームのオープン	
    let st = NSOutputStream(toFileAtPath: path, append: false)
    st!.open()

    // ストーリームの使用
    st!.write(&buffer, maxLength:100)
    st!.write(&buffer, maxLength:100)
    st!.write(&buffer, maxLength:100)
	
    // ストリームのクローズ    
    st!.close()
}

これが、条件による中断があるとなると、常にリソースの解放に注意が必要なります

func MyFunc(){
        
    // ストリームのオープン	
    let st = NSOutputStream(toFileAtPath: path, append: false)
    st!.open()

    st!.write(&buffer, maxLength:100)

    if !status { // 状態が変化していたら処理中断
         st!.close() // ストリームのクローズ 
	return
    }

    st!.write(&buffer, maxLength:100)

    if !status { // 状態が変化していたら処理中断
        st!.close() // ストリームのクローズ 
	return
    }
	
    st!.write(&buffer, maxLength:100)

    // ストリームのクローズ    
    st!.close()
}

そんな時は、リソースの確保と同時に、解放を書いておけばいいのでは無いでしょうか。

func MyFunc(){
        
    // ストリームのオープン	
    let st = NSOutputStream(toFileAtPath: path, append: false)
    st!.open()
    // オープンとセットでクローズ処理を書いてしまう
    defer{
    	st!.close() 
    }
		
    st!.write(&buffer, maxLength:100)

    if !status { return }

    st!.write(&buffer, maxLength:100)

    if !status { return }
	
    st!.write(&buffer, maxLength:100)
}

コードがスッキリするという意味ではなく、間違いが混入しにくくなるという意味で・・・
事後、条件分岐がより複雑になっても、リソース解放の処理に気を使う必要は無くなると思います。

ツッコミを恐れずに言ってしまうと、メソッドのデストラクタ?
「デストラクタ」・・・ちょっと懐かしい・・・

参考資料

https://medium.com/the-traveled-ios-developers-guide/swift-defer-bcef70de8767
The defer keyword in Swift 2: try/finally done right – Hacking with Swift