デモ
.swift
final class ViewController: UIViewController {
override func loadView() {
view = UILabel().apply { $0
.text("Apply Swift")
.textAlignment(.center)
.textColor(.white)
.font(.boldSystemFont(ofSize: 24))
.backgroundColor(.black)
}
}
}
私以外にもKotolinのapplyをSwiftでもやりたいと思ったことのある人はいるでしょう。
例えば以下のようにUILabelを定義する場面を考えます。
.swift
let label: UILabel = {
let it = UILabel()
it.text = "label.."
return it
}()
以前までは、以下のようなプロトコルを定義することで
.swift
protocol Applicatable {}
extension Applicatable {
func apply(_ closure: ((Self) -> ())) -> Self {
closure(self)
return self
}
}
extension NSObject: Applicatable {}
それっぽく実装することができました。
.swift
let label = UILabel().apply { it in
it.text = "label.."
}
しかし言語の進化により、もっとKotolinのapplyに近づけることができるようになりました。
つい先日DuctTapeというライブラリが公開されたのをきっかけにそれが可能になってたことを知りました。(Swiftのキャッチアップに遅れぎみです)
dynamicMemberLookup
Swift4.2で追加された機能ですが
.swift
@dynamicMemberLookup
struct StringMaker {
subscript(dynamicMember value: String) -> String {
return value
}
}
let maker = StringMaker()
debugPrint(maker.id) // String: id
debugPrint(maker.name) // String: name
Swift5.1からKeyPathを使えるようになったみたいです。
@dynamicMemberLookup attribute requires ‘xxx’ to have a ‘subscript(dynamicMember:)’ method that accepts either ‘ExpressibleByStringLiteral’ or a keypath
これを使って参考ライブラリをパクりつつインターフェースの変更を40行程度実装すると
.swift
let label = UILabel().apply { $0
.text("Apply Swift")
.textAlignment(.center)
.textColor(.white)
.backgroundColor(.black)
}
debugPrint(label.text) // Optional(Apply Swift)
上記のような実装をすることができました。
一応ソースはGistに公開しておきます。