LoginSignup
9
7

More than 5 years have passed since last update.

SwiftでWith...End Withステートメントっぽい書き方をする

Last updated at Posted at 2015-06-18

はじめに

UILabelに限った話ではないのですが、同じオブジェクトに対してそれなりの数のプロパティを設定することは以外と多いです。

(わざとらしい例ですが)以下のように。

fooBarHogeLabel.frame = CGRect(x: 10, y: 10, width: 100, height: 60)
fooBarHogeLabel.backgroundColor = UIColor.blueColor()
fooBarHogeLabel.textColor = UIColor.yellowColor()
fooBarHogeLabel.font = UIFont.boldSystemFontOfSize(15)
fooBarHogeLabel.textAlignment = NSTextAlignment.Center
fooBarHogeLabel.text = "Hello, world!"

個人的に、fooBarHogeLabel.というのが続いているのがどうも好きになれません。特に長い変数名の場合は可読性の低下にもつながります。

今日日、上記のような設定はStoryboard/xibでやれ(@IBInspectableで独自ViewについてもXcodeのデザイナ上で設定できるようになったこともあり)という話ではあるのですが、コード上で書きたいケースだってあります。

With...End Withステートメント

短い一時変数(labelとかlとか)を使うというのも手ではあるのですが、その為だけに一時変数を用意するのも・・・という感じもします。

そこでOptionalを拡張して、VB.NETで用意されているWith...End Withステートメントっぽく書いてみることにしました。

// Optionalを拡張してwithメソッドを追加
extension Optional {
    func with(f: T -> ()) {
        switch self {
        case .None: return
        case .Some(let x): f(x)
        }
    }
}

// withメソッドを利用したコード
let fooBarHogeLabel = UILabel()
Optional.Some(fooBarHogeLabel).with {

    // Swiftのクロージャ仕様で$0でアクセスできる
    $0.frame = CGRect(x: 10, y: 10, width: 100, height: 60)
    $0.backgroundColor = UIColor.blueColor()
    $0.textColor = UIColor.yellowColor()
    $0.font = UIFont.boldSystemFontOfSize(15)
    $0.textAlignment = NSTextAlignment.Center
    $0.text = "Hello, world!"
}

Optinalでない場合は上記のように一度ラップしてあげる必要がありますが、クロージャ内では$0という2文字でアクセスできます。

クロージャを利用しているので必然的にインデントを入れることになり、そのオブジェクトに対しての設定コードであることが分かりやすくなったようにも感じます。

追記:
コメントにてOptionalを利用しないベターな書き方を教えていただきました(Thanks! @satoshia

func with<T>(obj: T, setup: T -> T) -> T {
    return setup(obj)
}

let fooBarHogeLabel = with(UILabel()) {
    $0.frame = CGRect(x: 10, y: 10, width: 100, height: 60)
    $0.backgroundColor = UIColor.blueColor()
    $0.textColor = UIColor.yellowColor()
    $0.font = UIFont.boldSystemFontOfSize(15)
    $0.textAlignment = NSTextAlignment.Center
    $0.text = "Hello, world!"
    return $0
}

はたしてこれは読みやすいか?

どうしてこんなコードを書こうかと思った経緯を話しておくと、この前はじめてSpriteKitのコードを書いてみた時に、 1オブジェクトに対して設定するプロパティが多くて「わずらわしい!」と思った のがきっかけです。

で、問題はこの書き方が 本当に読みやすいか? ってことです。

個人的にはブラケットを利用したObjective-Cの初期化構文(ちょっと名前を忘れてしまいましたが)と似ているようにも感じられ、今のところ読みやすいと感じているのですが、一般的な書き方ではないですし、Xcodeを活用すればコーディング速度の面で有利とは感じません。

可読性は究極のところ好みの問題なので、プロジェクト内で一緒に開発するメンバーが書きやすいと思ったらこういう書き方もありなんじゃないでしょうか?

(という無難な締め方で)

--
P.S.
仕事仲間のSwift書きに意見を聞いてみたいと思ってます。

9
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7