首页 > 解决方案 > 在 RxDataSources 中对 SectionModelType 的“Self”要求进行初始化

问题描述

使用TableViewSectionedDataSource将分段表与RxDataSources绑定,需要符合SectionModelType的部分。

SectionModelType协议具有以下初始化程序作为其要求之一:

    init(original: Self, items: [Item])

此外,相同的协议强制执行var items: [Item] { get }. 我们现在可以init使用 fromoriginal.itemsitems作为 init 参数传递来初始化 items 数组支持变量(在上面提到的)。这非常令人困惑。SectionModelType 代码没有注释。

README 的How部分解释了为这种情况创建部分,讨论了创建类型别名(用于关联值)和 items 数组,但没有关于以下实现initwith的说法original: Self

init(original: SectionOfCustomData, items: [Item]) {
    self = original
    self.items = items
}

虽然这可以在结构中工作,但在类中做同样的喊叫:

无法赋值:'self' 是不可变的

任何人都可以在这里解释这里发生了什么以及为什么我们需要初始化Self

最后,是否有另一种(更清洁的)反应方式(仅在 RXSwift / RxCocoa 中)将分段表视图绑定到可观察数据源。例如 * 我的单元格和部分有自己的数据模型,它们需要是可变的(因此是类) * 有多个屏幕对不同的实体有这个要求,所以我会对用协议来实现这一点感兴趣,并拍下相应的具有协议 ans 的数据模型具有 RXBinding 的通用实现

任何可以更清楚地了解现有实现或实现上述要点的指针都会非常有帮助。PS:我已经在使用 Rx 的庞大代码库中工作,所以不使用 Rx,或者迁移到 SwiftUI 等不是我想要的。

标签: swiftrx-swiftrxdatasources

解决方案


init(original:items:)是一个拷贝初始化器。它采用结构的现有实例并创建一个相同的新实例,只是它更改了items属性中的内容。

所以在协议声明中,init(original: Self, items: [Item])意思是:“你给我一个已经存在的实例,无论这种类型符合我的协议,我们将创建一个新实例,在更改它的同时复制它items。”

这正是示例所做的。如果您将它们放在一起,则更容易查看,如下所示:

protocol SectionModelType {
    associatedtype Item
    var items: [Item] { get }
    init(original: Self, items: [Item])
}
struct CustomData {
    var anInt: Int
    var aString: String
    var aCGPoint: CGPoint
}
struct SectionOfCustomData {
    var header: String
    var items: [Item]
}
extension SectionOfCustomData: SectionModelType {
    typealias Item = CustomData
    init(original: SectionOfCustomData, items: [Item]) {
        self = original
        self.items = items
    }
}

在扩展的实现中,由您来决定他们所做的事情:设置selforiginal,这是一些已经存在的 SectionOfCustomData 对象(在结构初始化程序中是允许的),然后更改它的items. 而且您必须按此顺序执行此类操作,因为如果您不这样做,您将尝试在不设置其header属性的情况下初始化 SectionOfCustomData 对象 - 而通过这种方式,我们可以保证已经存在header属性值,因为我们是从一个已经存在的 SectionOfCustomData 对象开始的,如果设置它的header属性就无法创建一个。

至于你的另一个担心,如果这是一个类,而不是一个结构,那将无法编译:是的,你完全正确,但不要那样做。这不是他们说要做的。他们说把它变成一个结构,他们是认真的。


推荐阅读