KPDataBinding
一个具有 Swift KeyPath 的数据绑定库
安装
pod 'KPDataBinding'
特性
- 不仅在模型中,而且在视图中利用 KeyPath
- 单向和双向数据绑定
- 多个视图绑定到同一个模型的属性
- 数据格式和转换
- 中缀运算符
- 解除绑定
单向数据绑定
struct User {
var aString: String?
var aButtonTitle: String?
}
let userViewModel = KPDataBindingViewModel<User>()
userViewModel.bind(User(), [
uiLabel <- \User.aString,
uiButton <- \User.aButtonTitle,
])
userViewModel.update(\.aString, with: "A new text")
//userViewModel.model.aString == "A new text"
//uiLabel.text == "A new text"
userViewModel.update(\.aButtonTitle, with: "A new text")
//userViewModel.model.aButtonTitle == "A new text"
//uiButton.title(for: .normal) == "A new text"
单向数据绑定中的类型转换
- 格式化数据以在视图中显示
struct User {
var aInt: Int
}
userViewModel.bind(User(), [
uiLabel <~ (\User.aInt, toLabel: { $0.text = "Your Age: \($0)" }),
])
userViewModel.update(\.aInt, with: 1)
//userViewModel.model.aInt == 1
//uiLabel.text == "Your Age: 1"
双向数据绑定
struct User {
var aString: String?
var isOn: Bool
var isSelected: Bool
var isSelected: Bool
var aFloat: Float
var aDouble: Double
}
userViewModel.bind(initialData, [
uiTextField <-> \User.aString,
uiSwitcher <-> \User.isOn,
uiButton <-> \User.isSelected,
uiSlider <-> \User.aFloat,
uiSteper <-> \User.aDouble,
])
//view value and model value will be equal
//userViewModel.model.isOn == uiSwitcher.isOn
//userViewModel.model.isSelected == uiButton.isSelected
//userViewModel.model.aFloat == uiSlider.value
//userViewModel.model.aDouble == uiSteper.value
注意:UITextField的默认文本为@""。https://developer.apple.com/documentation/uikit/uitextfield/1619635-text
userViewModel.update(\.aString, with: nil)
//userViewModel.model.aString == nil
//uiTextField.text == ""
userViewModel.update(\.aString, with: "A new String")
//userViewModel.model.aString == "A new String"
//uiTextField.text == "A new String"
双向数据绑定中的格式化和类型转换
- 格式化数据以在视图中显示
- 类型转换视图值到模型
userViewModel.bind(initialData, [
ageSteper <~> (\User.age, { $0.value = Double($1) }, { view, _ in Int(view.value) }),
])
userViewModel.update(\.aInt, with: 1)
//userViewModel.model.aInt == 1
//uiSteper.value == Double(1)
//uiSteper's value changed to 3.0
//userViewModel.model.aInt == Int(3.0)
更新模型和视图
始终通过ViewModel更新模型,绑定视图将自动更新。
userViewModel.update(\User.name, with: "A new Name")
解绑
userViewModel.unbind(\User.name)
使用KPDataBinding在实际操作中的数据绑定
import KPDataBinding
class ViewController: UIViewController {
@IBOutlet weak var groupNameLbl: UILabel!
@IBOutlet weak var nameField: UITextField!
@IBOutlet weak var emailField: UITextField!
@IBOutlet weak var ageLbl: UILabel!
@IBOutlet weak var ageSteper: UIStepper!
@IBOutlet weak var activitySlider: UISlider!
@IBOutlet weak var likeKiwiSwitcher: UISwitch!
@IBOutlet weak var travelBtn: UIButton!
@IBOutlet weak var hikingBtn: UIButton!
@IBOutlet weak var readingBtn: UIButton!
lazy var userViewModel = KPDataBindingViewModel<User>()
override func viewDidLoad() {
let initialData = User(groupName: "Save NZ Animals Group 1", name: "Tonny")
userViewModel.bind(initialData, [
groupNameLbl <- \User.groupName,
travelBtn <- \User.name,
nameField <-> \User.name,
emailField <-> \User.email,
activitySlider <-> \User.activity,
likeKiwiSwitcher <-> \User.likeKiwi,
travelBtn <-> \User.travel,
hikingBtn <-> \User.hiking,
readingBtn <-> \User.reading,
ageLbl <~ (\User.age, { $0.text = "Your Age: \($1)" }),
ageSteper <~> (\User.age, { $0.value = Double($1) }, { view, _ in Int(view.value) }),
])
}
@IBAction func submit(_ sender: Any) {
let data = userViewModel.model
...
}
}
KPDataBinding如何与KeyPath结合使用?
model[keyPath: \User.name] = "Tonny" //update model
view[keyPath: \UITextField.text] = "Tonny" //update view
view[keyPath: \UITextField.text] = model[keyPath: \User.name] //update view from model
view.addTarget(self, #selector(viewChanged), for: event)
func viewChanged(view: UITextField) {
model[keyPath: \User.name] = view[keyPath: \UITextField.text] //update model from view
}
许可证
KPDataBinding 在 MIT 许可协议下可用。有关更多信息,请参阅 LICENSE 文件。