[英]How can I dynamically declare a variable type then use it as an argument when instantiating a custom view in SwiftUI?
我在做什么:
我正在制作一个可重用的tableView
并且刚刚完成,但是我无法在我的视图 model 中引用属性,因为我已将我的 model 类型声明为表视图结构中的AnyObject
。
我想在实例化tableView
时动态声明变量类型。
例如,这是我使用自定义表格视图的方式:
struct MyView: View {
@EnvironmentObject var myViewModel: MyViewModel
var body: some View {
return
CustomTableView(model: myViewModel as MyViewModel)
}
}
如您所见,我必须在视图中声明类型,因为我在表视图结构中使用AnyObject
类型。 这是因为 model 会根据我使用自定义表格视图的位置而有所不同,因此我需要灵活性。
这是我的表视图结构:
struct CustomTableView: UIViewRepresentable {
var model: AnyObject
class Coordinator: NSObject, UITableViewDelegate, UITableViewDataSource {
var customTableView: CustomTableView
let cellIdentifier = "MyCell"
init(_ customTableView: customTableView) {
self.customTableView = customTableView
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! MyTableViewCell
return cell
}
}
func makeCoordinator() -> DabbleTableView.Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITableView {
let cellIdentifier = "MyCell"
let tableView = UITableView()
tableView.delegate = context.coordinator
tableView.dataSource = context.coordinator
tableView.register(MyTableViewCell.self, forCellReuseIdentifier: cellIdentifier)
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return tableView
}
func updateUIView(_ uiViewController: UITableView, context: Context) {
}
}
我想做的事:
要么让表视图自动使用在实例化表视图时声明的ViewModel
类型名称,要么在实例化表视图时传入正确的ViewModel
类型。
我不清楚如何做到这一点。 我在想类型别名可能有用,但我读得越多,我就越意识到这不是正确的解决方案。
将类型作为字符串传递不起作用,因为 Swift 会将参数识别为字符串。
最干净的方法是什么?
提前致谢。
可能的方法是使用 generics (如果/需要时也符合任何自定义协议),因此您不需要转换类型并将其用作
struct MyView: View {
@EnvironmentObject var myViewModel: MyViewModel
var body: some View {
CustomTableView(model: myViewModel)
}
}
所以CustomTableView
应该声明为
struct CustomTableView<Model:ObservableObject>: UIViewRepresentable {
var model: Model
...
使用 Xcode 11.4 / iOS 13.4 测试
更新:下面是可编译的例子
// base protocol for CustomTableView model
protocol CustomTableViewModel {
func numberOfSections() -> Int
func numberOfRows(in section: Int) -> Int
}
// some specific model
class MyViewModel: ObservableObject, CustomTableViewModel {
func numberOfSections() -> Int { 1 }
func numberOfRows(in section: Int) -> Int { 7 }
}
// usage
struct MyView: View {
@EnvironmentObject var myViewModel: MyViewModel
var body: some View {
CustomTableView(model: myViewModel)
}
}
// generic table view
struct CustomTableView<Model:ObservableObject & CustomTableViewModel>: UIViewRepresentable {
var model: Model
class Coordinator: NSObject, UITableViewDelegate, UITableViewDataSource {
var customTableView: CustomTableView
let cellIdentifier = "MyCell"
init(_ customTableView: CustomTableView) {
self.customTableView = customTableView
}
func numberOfSections(in tableView: UITableView) -> Int {
customTableView.model.numberOfSections()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
customTableView.model.numberOfRows(in: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! MyTableViewCell
return cell
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITableView {
let cellIdentifier = "MyCell"
let tableView = UITableView()
tableView.delegate = context.coordinator
tableView.dataSource = context.coordinator
tableView.register(MyTableViewCell.self, forCellReuseIdentifier: cellIdentifier)
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
return tableView
}
func updateUIView(_ uiViewController: UITableView, context: Context) {
}
}
class MyTableViewCell: UITableViewCell { }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.