役に立つかどうかよくわからないTipsシリーズ
あるきっかけで、このQiita記事を紹介していただきました
SwiftでKotlinのapplyっぽいものを使いたい
その内容によると
protocol ApplyProtocol {}
extension ApplyProtocol {
func apply(closure: (this: Self) -> Void) -> Self {
closure(this: self)
return self
}
}
extension NSObject: ApplyProtocol {}
addSubview(UILabel().apply { this in
this.frame = CGRectMake(0, 0, 100, 100)
this.text = "swift"
this.textColor = UIColor.cyanColor()
})
Kotlinって使ったことなかった人間なので「なるほどー、良い感じ」と
思って記事を読ませていただきました
(投稿者の方に拍手)
ただ、ちょっとだけ遊びでいじってみたくなりました
上のコードだと例えば UIViewController
の view
に
UILabel
を配置した上で、メンバ変数として持たせたい時に
こんな感じで書くことになるかなぁと
class ViewController: UIViewController {
private var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.label = UILabel().apply { this in
this.frame = CGRectMake(0, 0, 100, 100)
this.text = "swift"
this.textColor = UIColor.cyanColor()
self.view.addSubview(this)
}
}
}
これでも全然いいと思うのですが、
そもそも短くしたかったソースコードが、減っていない感じになってしまいました
そこで「UIView
の extension
を咬ませて、シンプルにできないだろうか?」と
試行錯誤してみてこのようになりました
// == 参考記事の実装 ==
protocol ApplyProtocol {}
extension ApplyProtocol {
func apply(closure: (this: Self) -> Void) -> Self {
closure(this: self)
return self
}
}
extension NSObject: ApplyProtocol {}
// == 下記を追加 ==
extension UIView {
func addSubview<T: ApplyProtocol where T: UIView>(view: T, apply applyClosure: (this: T) -> Void) -> T {
let ret = view.apply(applyClosure)
self.addSubview(ret)
return ret
}
}
既存の addSubview
に オーバロードするような形で
apply内容を書き増しさせることができる・・・という感じです
で、コントローラ側の実装はこうなりました
class ViewController: UIViewController {
private var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.label = self.view.addSubview(UILabel()) { this in
this.frame = CGRectMake(0, 0, 100, 100)
this.text = "swift"
this.textColor = UIColor.cyanColor()
}
}
}
シンプルに・・・なったと個人的には思いましたが、、
うーん、好みかもしれません