Swift 将UITableView与合并数据源绑定
我想直接将Swift 将UITableView与合并数据源绑定,swift,combine,Swift,Combine,我想直接将UITableView链接到@Published属性,而不使用DiffableDataSouce 如果我让这个人 struct Person { let name: String } 并创建数据数组: @Published var people = [Person(name: "Kim"), Person(name: "Charles")] 所以我想直接绑定我的UITableView,比如: func tableView(tableV
UITableView
链接到@Published属性,而不使用DiffableDataSouce
如果我让这个人
struct Person {
let name: String
}
并创建数据数组:
@Published
var people = [Person(name: "Kim"), Person(name: "Charles")]
所以我想直接绑定我的UITableView
,比如:
func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
返回$people.count()
}
但这就产生了错误
无法将类型为“Publisher.Count.Publisher>”的返回表达式转换为返回类型“Int”
这里的问题是UITableViewDataSource是基于pull的(框架从代码中提取数据),但发布者是基于push的(它们将数据推送到某物上)。这意味着为了使其工作,您需要一个中介(a)调解人模式
一种选择是引入RxSwift/RxCocoa和RxCombine项目,以便在Combine和RxSwift之间进行转换,并在已经存在的地方使用功能。这一问题的内容很多,但也许RxCocoa还可以在其他方面简化代码
就这个问题,我认为有一位调解人会起作用:
final class ViewController: UIViewController {
var tableView: UITableView!
@Published var people = [Person(name: "Kim"), Person(name: "Charles")]
var cancellable: AnyCancellable?
override func viewDidLoad() {
super.viewDidLoad()
cancellable = $people.sink(receiveValue: tableView.items { tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = item.name
return cell
})
}
}
extension UITableView {
func items<Element>(_ builder: @escaping (UITableView, IndexPath, Element) -> UITableViewCell) -> ([Element]) -> Void {
let dataSource = CombineTableViewDataSource(builder: builder)
return { items in
dataSource.pushElements(items, to: self)
}
}
}
class CombineTableViewDataSource<Element>: NSObject, UITableViewDataSource {
let build: (UITableView, IndexPath, Element) -> UITableViewCell
var elements: [Element] = []
init(builder: @escaping (UITableView, IndexPath, Element) -> UITableViewCell) {
build = builder
super.init()
}
func pushElements(_ elements: [Element], to tableView: UITableView) {
self.elements = elements
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
elements.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
build(tableView, indexPath, elements[indexPath.row])
}
}
final类ViewController:UIViewController{
var tableView:UITableView!
@发布的var人员=[人员(姓名:“Kim”)、人员(姓名:“Charles”)]
var可取消:任何可取消?
重写func viewDidLoad(){
super.viewDidLoad()
Cancelable=$people.sink(receiveValue:tableView.items{tableView,indexPath,中的项
let cell=tableView.dequeueReusableCell(带有标识符:“cell”,用于:indexath)
cell.textLabel?.text=item.name
返回单元
})
}
}
扩展UITableView{
func项(ubuilder:@escaping(UITableView,IndexPath,Element)->UITableViewCell)->([Element])->Void{
让dataSource=CombineTableViewDataSource(生成器:生成器)
返回中的{项
pushElements(项,到:self)
}
}
}
类CombineTableViewDataSource:NSObject,UITableViewDataSource{
让我们构建:(UITableView,indexath,Element)->UITableViewCell
变量元素:[Element]=[]
init(生成器:@escaping(UITableView,IndexPath,Element)->UITableViewCell){
build=builder
super.init()
}
func pushElements(elements:[Element],到tableView:UITableView){
self.elements=元素
tableView.reloadData()
}
func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
元素数
}
func tableView(tableView:UITableView,cellForRowAt indexath:indexPath)->UITableViewCell{
构建(tableView、indexPath、元素[indexPath.row])
}
}
如果人员是同一类中的属性,则@Published不是正确的属性包装器。此处的真实数据源是什么?它将位于viewmodel中。