我使用的Siesta带有API,它为根实体返回非常轻量级的列表响应。例如,对于/entity
,这就是响应的样子:
{
count: 200,
results: [
{
url: "https://example.com/api/entity/1/",
name: "foo"
},
{
url: "https://example.com/api/entity/2/",
name: "bar"
},
{
url: "https://example.com/api/entity/3/",
name: "bat"
}]
}
在结果中的url
处找到的完整对象有一个avatar
属性,我真的很想在这个列表的表视图中显示它,但我不知道如何使用Siesta框架实现这一点。作为加载/entity
列表资源的一部分,是否可以从底层/entity/1
端点获取更多详细信息?
在Siesta的世界观中,一个url⟺一个资源。因此,有一个"摘要列表"资源/entity
,加上每行一个单独的"实体详细信息"资源/entity/1
等。它们碰巧共享一些相同的数据并不重要;Siesta本身不会对一个资源与另一个资源进行合并、同步或预填充。独立的URL,独立的资源。
经验法则是,"如果您需要来自资源的数据,请观察该资源。"由于您希望同时使用/entities
中的摘要信息和/entities/n
中的详细信息,因此您可以观察这两种资源。
以下是您可能使用的方法的示意图:
- 获取只显示
/entities
信息的表格视图,不显示头像。您可以使用示例项目中的RepositoryListViewController作为起点 -
使每个表单元格接受一个摘要模型,并观察其相应的详细资源:
class EntityTableViewCell: UITableViewCell, ResourceObserver { @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var avatar: RemoteImageView! private var summary: EntitySummary? private var detailResource: Resource? func showEntity(summary: EntitySummary) { self.summary = summary detailResource?.removeObservers(ownedBy: self) detailResource = MyApi.resource(absoluteURL: summary?.url) detailResource.addObserver(self).loadIfNeeded() }
-
现在在
resourceChanged()
中填充单元格,根据您认为合适的汇总和细节进行混合和匹配:func resourceChanged(resource: Resource, event: ResourceEvent) { let detail: EntityDetail? = detailResource?.typedContent() nameLabel.text = detail?.name ?? summary?.name avatar.imageURL = detail?.avatar }
-
当细胞移出视野时,你可能还想停止观察:
override func prepareForReuse() { showEntity(nil) } }
(这个草图假设您有单独的EntitySummary
和EntityDetail
模型。您也可能有一个Entity
模型,其中只有细节字段是可选的,或者您可能只是使用原始JSON字典。不管怎样,方法都是一样的。(
以下是当单元格滚动到视图中时会发生的情况:
- 您的
cellForRowAtIndexPath
调用showEntity(_:)
,传递它从/entities
资源获得的EntitySummary
- 细胞开始观察CCD_ 19
- 此立即触发
resourceChanged()
。详细信息资源还没有数据,因此您的单元格立即只填充摘要信息 - 最终加载详细信息资源。如果你的细胞仍在观察它,那么
resourceChanged()
会再次被调用,这次它会看到详细信息
请注意,在#4中,如果您的单元格在加载详细信息资源之前被滚动出视图并重新使用,那么您的单元格将不再观察它——因此,延迟到达的响应将而不是阻塞重新使用的单元格的内容。