Composed 是一个面向协议的框架,用于组合应用中来自各种来源的数据。它为常见的用例提供了各种具体的实现。
如果您更喜欢查看代码,这里有一个演示项目:ComposedDemo
该库将所有内容都基于两个基本元素:Section
和 SectionProvider
。
使用 Composed 的主要好处包括:
Composed 包含 3 个预定义的 section 以及 2 个 provider,应该可以满足大多数应用程序的需求。
ArraySection 表示通过 Array
管理其元素的 section。这种类型的 section 适用于表示内存中的数据。
ManagedSection 表示通过 NSFetchedResultsController
提供其元素的 section。此 section 适用于表示由 CoreData 管理的数据。
SingleElementSection 表示管理单个元素的 section。此 section 适用于只有单个元素要管理的情况。提示:使用 Optional<T>
来表示可能存在也可能不存在的元素。
ComposedSectionProvider 表示 Section
和 SectionProvider
的集合。该 provider 支持无限嵌套,包括其他 ComposedSectionProvider
。所有子项将始终处于活动状态,因此 numberOfSections
和 numberOfElements(in:)
将返回代表所有子项的值。
SegmentedSectionProvider 表示 Section
和 SectionProvider
的集合。该 provider 支持无限嵌套,包括其他 SegmentedSectionProvider
。任何时候都只有一个或零个子项可能处于活动状态,因此 numberOfSections
和 numberOfElements(in:)
将仅返回代表当前活动子项的值。
假设我们想要表示用户的联系人库。我们的联系人将有 2 个组:家人和朋友。使用 Composed,我们可以轻松地将其建模如下:
let family = ArraySection<Person>()
family.append(Person(name: "Dad"))
family.append(Person(name: "Mum"))
let friends = ArraySection<Person>()
friends.append(Person(name: "Best mate"))
此时,我们有两个单独的 section 用于表示我们的两组联系人。现在我们可以使用一个 provider 将这两个 section 组合在一起:
let contacts = ComposedSectionProvider()
contacts.append(family)
contacts.append(friends)
就是这样!现在我们可以使用 provider 查询我们的数据,而无需任何一个单独的 section 知道它们现在包含在更大的结构中。
contacts.numberOfSections // 2
contacts.numberOfElements(in: 1) // 1
如果我们想查询 section 中的单个数据(假设我们还没有对它的引用):
let people = contacts.sections[0] as? ArraySection<Person>
people.element(at: 1) // Mum
注意:我们必须将 section 转换为已知类型,因为 SectionProvider 可以包含任何类型的 section 以及其他嵌套的 provider。
如果我们现在继承 ArraySection,我们可以通过协议一致性来扩展我们的 section,以做一些更有趣的事情:
final class People: ArraySection<Person> { ... }
protocol SelectionHandling: Section {
func didSelect(at index: Int)
}
extension People: SelectionHandling {
func didSelect(at index: Int) {
let person = element(at: index)
print(person.name)
}
}
为了使这个工作正常进行,某些东西需要调用 didSelect
,因此为了本示例的目的,我们将省略一些细节,但让您预览一下如何自己构建类似的东西:
// Assume we want to select the 2nd element in the 1st section
let section = provider.sections[0] as? SelectionHandling
section?.didSelect(at: 1) // Mum
Composed 正在处理所有的映射和结构,允许我们完全专注于行为和扩展。
Section 正如其名称所示,代表单个 section。最好的事情是,我们在一个 section 中不需要 IndexPath
,只需要索引!
Section provider 是一种容器类型,包含 section 或其他 provider。允许无限嵌套,因此具有无限的可能性。
Mappings 提供了你的“树”结构和最终的 flattened
结构之间的粘合剂。让我们看一个例子。
// we can define our structure as such:
- Provider
- Section 1
- Provider
- Section 2
- Section 3
- Section 4
// mappings will then convert this to:
- Section 1
- Section 2
- Section 3
- Section 4
此外,mappings 负责从本地索引到全局索引的转换,更重要的是负责 IndexPath
的转换,这使得更多有趣的用例成为可能。
要了解更多信息,请查看 ComposedUI,它提供了与
UICollectionView
和UITableView
配合使用的用户界面实现,允许您从简单的可重用Section
驱动整个屏幕。