LoginSignup
8
5

More than 3 years have passed since last update.

【Swift】メソッドチェーンで見やすく

Last updated at Posted at 2021-03-27

はじめに

コードでUIを作成するときに、メソッドチェーンを使いえば見やすくなるので、それを紹介します。
本当はジェネリクスなども使ったほうがいいのですが、今回は使いません。

メソッドチェーンとは?

その名の通り、メソッドを鎖(チェーン)のように書いていくということです。
例えば、普通は以下のように書くと思います。

let label = UILabel()
label.frame.origin = CGPoint(x: 100, y: 100)
label.frame.size = CGSize(width: 100, height: 40)
label.text = "text"
label.layer.cornerRadius = 25
label.backgroundColor = .red
label.textColor = .white
label.textAlignment = .center
self.view.addSubview(label)

これでもいいのですが、これだとlabelを複数書いるのでもう少し見やすく書けないか考えてみます。
メソッドチェーンをつかえば以下のように書くことができます。

let label = UILabel()
    .origin(x: 100, y: 100)
    .size(width: 100, height: 40)
    .backgroundColor(.red)
    .cornerRadius(25)
    .text("テキスト")
    .textColor(.white)
    .textAlignment(.center)
self.view.addSubview(label)

こちらの方が、すっきりしていていいですよね。

実装

メソッドチェーンのポイントはreturn self です。
例えば、.origin(x: 100, y: 100)を例にとってみましょう。
UILabelはUIViewを継承しているので、UIViewをextensionしてみましょう。

extension UIView {
    func origin(x: CGFloat, y: CGFloat) -> Self {
        self.frame.origin = CGPoint(x: x, y: y)
        return self
    }
}

self.frame.originのselfはこのoriginメソッドを使うものを表しています。今で言うと定数labelですね。
戻り値に大文字のSelfを使うことで、戻り値をUIViewにし、メソッドを鎖のように連ねていくことができるというわけです。
これを今回を例に全て書いてあげると、

extension UIView {
    func origin(x: CGFloat, y: CGFloat) -> Self {
        self.frame.origin = CGPoint(x: x, y: y)
        return self
    }
    func size(width: CGFloat, height: CGFloat) -> Self {
        self.frame.size = CGSize(width: width, height: height)
        return self
    }
    func backgroundColor(_ color: UIColor) -> Self {
        self.backgroundColor = color
        return self
    }
    func cornerRadius(_ radius: CGFloat) -> Self {
        self.layer.cornerRadius = radius
        return self
    }
}

extension UILabel {
    func text(_ text: String) -> Self {
        self.text = text
        return self
    }
    func textColor(_ color: UIColor) -> Self {
        self.textColor = textColor
        return self
    }
    func textAlignment(_ alignment: NSTextAlignment) -> Self {
        self.textAlignment = alignment
        return self
    }
}

このようにしてあげることで、メソッドチェーンが使用可能になります。

番外編

番外編として、クロージャでもかけるので、それを紹介しておきます。

extension UILabel {
    func chain(_ closure: (Self) -> Void) -> Self {
        closure(self)
        return self
    }
}
let closureLabel = UILabel()
    .chain { label in
        label.frame.origin = CGPoint(x: 100, y: 100)
        label.frame.size = CGSize(width: 100, height: 40)
        label.backgroundColor = .red
        label.layer.cornerRadius = 25
        label.text = "text"
        label.textColor = .white
        label.textAlignment = .center
    }
self.view.addSubview(closureLabel)

こちらはわざわざ一つ一つメソッドを定義しなくても容易ので、楽ですね。

おわりに

おわりです。

8
5
0

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
8
5