チェインメソッドで少しだけ楽にキレイにする

More than 1 year has passed since last update.

みなさんチェインメソッド使ってますか?

後ろを見ずに突き進む感じいいですよね。

Swiftでチェインメソッド組めないか少し考えてみました。


まずはUIButtonを普通に初期化するところから

let button = UIButton()

button.frame = CGRect(x: 0, y: 0, width: 500, height: 250)
button.setTitle("Close", forState: .Normal)


総称(Generics)

class Chain<T>{

private var val:T
init( val:T ){
self.val = val
}
func next( execute:(T) -> Void ) -> Chain<T>{
execute(val)
return self
}
func end() -> T {
return val
}
}

let button2 = Chain<UIButton>(val: UIButton())
.next({$0.frame = CGRect(x: 0, y: 0, width: 500, height: 250)})
.next({$0.setTitle("Close", forState: .Normal)}).end()

なんだかクロージャがゴチャゴチャです。

ブロックが2種類挟まないといけないのも面倒です。


継承

class ChainButton : Chain<UIButton> {

init(frame:CGRect){
super.init(val: UIButton(frame:frame))
}
func title(label:String) -> ChainButton{
next({$0.setTitle(label, forState: .Normal)})
return self
}
func cornerRadius(rad:CGFloat) -> ChainButton{
next({$0.layer.cornerRadius = rad})
return self
}
func borderWidth(width:CGFloat) -> ChainButton {
next({$0.layer.borderWidth = width})
return self
}
func borderColor(color:UIColor) -> ChainButton {
next({$0.layer.borderColor = color.CGColor})
return self
}
func backgroundColor(color:UIColor) -> ChainButton {
next({$0.backgroundColor = color})
return self
}
}

let button3 = ChainButton(frame:CGRect(x: 0, y: 0, width: 300, height: 70))
.title("Title")
.cornerRadius(0.5)
.borderWidth(1)
.borderColor(UIColor.redColor()).end()

それっぽくなりました。

ChainButtonというクラスの存在が非常に助長で、C++の特殊化使えれば、そこんとこスマートになるのですが、どうやらSwiftではそこまでサポートされていないようです。

なので、「よく使うメソッドをチェーン化はじめました」というポリシーにするしかなさそうです。

当初の3行を何十回何百回と書く場合にようやくペイできそうな感じですね。

あと気になるのは、CGRectが長く見えるので、配列で渡せるようにすればも少し短くなりそうですね。


Playgroundで作りました。