はじめに
コードで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)
こちらはわざわざ一つ一つメソッドを定義しなくても容易ので、楽ですね。
おわりに
おわりです。