こんな書き方できたんだ!?

今日貯めてた Reading List を見てたらこんな記事が。

New thing I do in code

以下のようなコードが動きます。

self.downloadButton = ({
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    NSLog(@"%s %@", __PRETTY_FUNCTION__, button);
    button.frame = CGRectMake(40, 40, 100, 50);
    [button setTitle:@"Donwload" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    button; 
});

ここでボタンにセットしたアクションのログ(sender と self.downloadButton を出力) を見ても、生成したボタンが self.downloadButton に代入されていることが分かります。

2013-08-20 21:26:22.062 SampleApp[60019:c07] -[TestViewController viewDidLoad] <UIRoundedRectButton: 0x1101fc10; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x1101fce0>>
2013-08-20 21:26:24.007 SampleApp[60019:c07] -[TestViewController buttonAction:] <UIRoundedRectButton: 0x1101fc10; frame = (40 40; 100 50); opaque = NO; layer = <CALayer: 0x1101fce0>>
2013-08-20 21:26:24.007 SampleApp[60019:c07] -[TestViewController buttonAction:] <UIRoundedRectButton: 0x1101fc10; frame = (40 40; 100 50); opaque = NO; layer = <CALayer: 0x1101fce0>>

GCC の拡張で丸括弧で囲われたの中括弧内の記述が評価されるようです。仕様は以下のページに書かれています。

Statements and Declarations in Expressions

利点

さきの記事でも書かれていることですがこんな利点があります。

処理の塊が視覚的に明確

例に挙げた UIButton の生成の場合、インスタンス生成後に画像だったりタイトルだったりと結構な量のコードを書いたりします。普通に書いた場合これがフラットに並んでしまうのでどこまでが button の設定なのかが少し見づらい感じになってしまいます。(実際にはプロパティーで宣言してゲッター内で生成処理を書くのでスコープとかも明確な事が多いとは思いますが)今回知った手法だと括弧で囲われてインデントされるので視覚的にわかりやすいです。

変数のスコープが切れることで変数名衝突回避

今回の例だとあまり困ることはないかもしれませんが、frame 等を複数の弄るようなコードを書く場合、スコープが別れていない場合には一時変数の名称が冗長になったり使い回しをして変な挙動になったりしていろいろと辛い感じになります。今回知った手法だとスコープが別れることで CGRect frame とかっていう普通の名前を連発しても問題ありません。

エラーが出ることで代入忘れを防止

以前書いたエントリと同様の効果ですが、最後の行に戻り値を書いてないとエラーがでるので特に Frame を弄ったあとに Frame を代入しわすれて期待の動きにならないっていう凡ミスが防げます。

まとめ

正直、厳格な仕様を理解しきれていないので本当に使っても大丈夫なのか?挙動に罠がないのか?という部分はわかりませんが、可読性と凡ミス防止には有効だと思いますし、以前書いたエントリのような下準備も不要で気軽に使えそうなのがいいですね。