Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

はじめに

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書きに意見を聞いてみたいと思ってます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした