5

这是一个玩具示例,但它完全减少了我所处的情况:

class MyDataSource: UITableViewDiffableDataSource<String,String> {
    var string : String?
    init(string:String?) {
        self.string = string
        super.init(tableView: UITableView()) { (_, _, _) -> UITableViewCell? in
            print(self.string) // error
            return nil
        }
    }
}

我正在尝试使我的表视图数据源自包含,而我这样做的方式(到目前为止)是将 UITableViewDiffableDataSource 子类化。这很好用,除非我尝试给我的子类一个自定义初始化程序。玩具示例显示了问题。

我想要填充单元格的方式绝对取决于可以在数据源生命周期后期更改的值。因此,它不能硬编码到单元提供程序函数中。我不能在这里简单地引用string初始化器中传递的值;我必须参考,self.string因为稍后其他代码将有权更改此数据源的string实例属性,并且我希望单元提供程序在发生这种情况时使用该新值。

但是,我收到错误“在所有成员初始化之前由闭包自我捕获”。这似乎不公平。我确实string在调用之前初始化了我的实例属性super.init。因此,在可能调用单元格提供程序方法的最早时刻,它确实具有价值。

4

3 回答 3

5

您可以self通过访问tableView.datasource,它将解决大部分问题。

于 2020-02-16T20:09:31.290 回答
5

虽然我不完全确定为什么Swift 不允许这样做(与捕获self以在实际调用之前创建闭包有关super.init),但我至少知道它的解决方法。而是捕获一个弱局部变量,并在调用后将该super.init局部变量设置为self

class MyDataSource: UITableViewDiffableDataSource<String,String> {
    var string : String?
    init(string:String?) {
        self.string = string
        weak var selfWorkaround: MyDataSource?
        super.init(tableView: UITableView()) { (_, _, _) -> UITableViewCell? in
            print(selfWorkaround?.string)
            return nil
        }

        selfWorkaround = self
    }
}

但是,唯一的问题是,如果在调用 的过程super.init中执行了闭包,那么selfWorkaround闭包内部将是 nil 并且您可能会得到意想不到的结果。(不过,在这种情况下,我认为不是——所以你应该安全地这样做。)

编辑:我们制作局部变量的原因weak是为了防止self对象被泄露。

于 2020-02-16T20:12:22.860 回答
2

扩展 Abhiraj Kumar 从 2020 年 2 月 16 日起的回答,这是一个使用提供的 TableView 来“返回”以获取您附加到表格的数据源的示例......即“自我”:

class MyDataSource: UITableViewDiffableDataSource<String,String> {
    var string : String?
    init(string:String?) {
        self.string = string
        super.init(tableView: UITableView()) { (tableView, _, _) -> UITableViewCell? in
            
            // Very sketchy reach-through to get "self", forced by API design where
            // super.init() requires closure as a parameter
            let hack_self = tableView.dataSource! as! MyDataSource
            
            let selfDotStr = hack_self.string
            
            print("In closure, self.string is \(selfDotStr)")
            
            return nil // would return a real cell here in real application
        }
    }
}
于 2020-08-20T20:38:25.593 回答