PJFDataSource
PJFDataSource 是一个小型库,为您的应用程序提供了一种简单、清晰的架构来管理其数据源,同时为常见的内容状态(例如,加载、加载完成、空和错误)提供一致的用户界面。
灵感
PJFDataSource 是作为一个比 Apple 的 AdvancedCollectionView 示例代码更简单、更集中的替代品而构建的,该示例代码最初在 2014 年 WWDC 演示中引入,演示了 Advanced User Interfaces with Collection Views。
我们保留了喜欢的简单模式,但丢弃了大多数更复杂的功能。例如,PJFDataSource 没有任何内置的“聚合数据源”支持。它也不处理您实际视图的内容(例如配置和显示 UICollectionViewCells)。它甚至不要求您使用 UICollectionView。您的应用程序继续负责提供和配置用户界面内容视图,从而让您有弹性地选择表格视图、集合视图、堆叠视图等。
安装
CocoaPods
要将PJFDataSource安装到您的iOS项目中,使用CocoaPods进行安装。
platform :ios, '11.0'
pod 'PJFDataSource'
示例
为了更具体地了解PJFDataSource的功能,请查看此仓库中包含的简单演示应用程序。
- 将此仓库克隆到您的计算机上。
- 在Xcode中打开
PJFDataSource.xcodeproj
。 - 将您的目标切换为PJFDataSourceDemoApp并运行。
演示应用程序将在iOS模拟器中打开,显示一个表格视图,其中包含许多彩色行。这是我们简单的内容视图,一个UITableView。顶部有三个按钮,分别标记为“成功”、“空”和“错误”,它们简单地告诉演示应用程序重新加载数据,并模拟成功响应、空响应或错误响应。试用每个选项并注意。
- 点击任何按钮都会触发内容重新加载。注意,UI在等待异步数据加载时会过渡到显示加载指示器。您可以通过
UIAppearance
协议在PJFLoadingView
上自定义加载指示器图片。 - 点击“空”按钮将模拟在无错误的情况下加载数据,但确定它没有要显示的内容(见
-[PJFDataSource hasContent]
)。UI提供了一个显示图片/标题/消息和操作的方式,通过您的PJFContentWrapperViewDelegate
进行配置。您可以使用UIAppearance
协议在PJFImageTitleMessageView
上自定义此占位符视图的外观。 - 点击“错误”按钮将模拟加载内容时出现错误,并提供类似的占位符UI。您的
PJFContentWrapperViewDelegate
提供了底层的NSError
对象,因此您可以根据具体的错误自定义UI。 - 尝试连续多次点击其中一个按钮,然后快速点击另一个按钮。您会看到最终的UI将反映您的最后一次点击,忽略早期请求的响应。请参阅
PJFLoadingCoordinator
和单布尔“状态机”PJFLoadingState
。
这就全部了!
用法
您的应用与PJFDataSource之间有两个主要交互点:
PJFContentWrapperView
,您将插入到视图层次结构中的包装视图。PJFDataSource组件将与内容包装视图协同工作,在您提供的内容视图和PJFDataSource提供的加载/空/错误状态的视图之间切换。PJFDataSource
是一个抽象类,您需要为每个数据源分别进行子类化。数据源负责加载内容,更新其内部模型以反映已加载的内容,并通过其loadingCoordinator
通知成功或失败。通常,您的数据源也将作为内容视图的数据源(例如作为UITableView
的UITableViewDataSource
)。
在您的应用程序中基本集成如下所示
- 创建一个将拥有您想显示的内容视图的视图控制器。
- 在视图控制器中,使用
initWithFrame:contentView:
方法实例化一个PJFContentWrapperView
,传入您选择的内容视图(例如,一个UITableView
)。将包装视图插入到视图层次结构中的适当位置——可能作为根view
的全尺寸子视图。虽然不是必需的,但您可能想要将视图控制器设置为包装视图的PJFContentWrapperViewDelegate
,并实现至少willShowNoContentView:
和willShowErrorView:
以自定义这些占位符视图的内容。 - 在视图控制器中,实例化您的
PJFDataSource
子类(见下文),将视图控制器作为代理。实现contentWrapperViewForDataSource:
,这是PJFDataSourceDelegate
协议上唯一的必需方法,使其返回上述创建的内容包装视图。 - 在视图控制器的
viewWillAppear:
方法中,调用数据源的loadContent
。
您现在拥有了您自己的PJFDataSource
子类实例。您正在告诉它在视图控制器出现时加载。数据源执行其工作并适当更新内容包装视图。哇!
-[PJFDataSource loadContent]
示例正确实现您的loadContent
方法非常重要,且从API中并不完全明显。关键是PJFDataSource实例使用其提供的PJFLoadingCoordinator
来实际启动加载,并通知成功或失败。请参阅此示例,直接从演示应用程序中获取
- (void)loadContent;
{
[self.loadingCoordinator loadContentWithBlock:^(PJFLoadingState *loadingState) {
[self.colorsLoader asyncLoadColorsWithSuccess:^(NSArray *colors) {
if (!loadingState.valid) {
return;
}
self.colors = colors;
[self.loadingCoordinator loadContentDidFinishWithError:nil];
} error:^(NSError *error) {
if (!loadingState.valid) {
return;
}
[self.loadingCoordinator loadContentDidFinishWithError:error];
}];
}];
}
由PJFDataSource基类提供的self.loadingCoordinator
对象。当您开始加载内容时,请通过loadContentWithBlock:
方法进行加载。这使得加载协调器知道您何时开始加载,并允许它提供一个PJFLoadingState
对象,以便我们可以忽略来自过期请求的响应(即由最新请求所撤销)。
在loadContentWithBlock:
块内,您将启动异步加载任务,并具有完成时的回调。在这种情况下,我们使用另一个对象(self.colorsLoader
)来完成这项繁重的工作。在我们的完成块中,我们检查loadingState
以确定它是否仍在当前状态。如果不是,我们将立即忽略这个响应。如果是,我们将更新我们的内部模型(例如,self.colors = colors;
),然后通过loadContentDidFinishWithError:
通知我们的loadingCoordinator
成功或失败。
外观样式
PJFDataSource通过UIAppearance机制提供有限的外观样式。请参阅UI_APPEARANCE_SELECTOR
的属性。还可以查看演示应用中的AppAppearance
类,其唯一目的是设置外观样式。
缺少的功能
我们希望保持PJFDataSource简单,但我们知道我们想添加一些功能
- 通过
UIAppearance
协议增加PJFImageTitleMessageView
的定制性 - 自定义应用到PJFLoadingView加载图像上的动画(目前是旋转动画)
如果您想帮忙,请参阅下方的“贡献”部分。
需求
- iOS 8或更高版本。
贡献
我们很高兴您对PJFDataSource感兴趣,我们很乐意看到您的进展。在提交拉取请求之前,请阅读我们的贡献指南。