Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 将UITableView与合并数据源绑定_Swift_Combine - Fatal编程技术网

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中。