这是一个小型库,简化了您的工作,允许您通过某些参数分块加载数据。它承担了分页数据加载的常见职责:防止对同一页面的多个请求、跟踪已加载数据范围、提供下一页/上一页参数。
要运行示例项目,请克隆仓库,并首先在 Example 目录中运行 pod install
。同样的方法,您可以在 ExampleSwift 目录中运行 Swift 示例项目。
它应该可以正常工作在旧版本上,但在 Xcode 9.1 上在 iOS 8.4 及更高版本上进行了测试。
分页器通过 CocoaPods 提供。要安装
它,只需在您的 Podfile 中添加以下行
pod 'Paginator'
此安装将只提供所有需要的协议的核心类。
如果您还希望使用提供的分页参数提供程序之一(或全部),则需要添加
pod 'Paginator/ParametersProviders'
然后运行 pod install
。
您还可以仅复制 Classes 目录中的所有文件(是否包含 PagingParametersProviders 的文件取决于您的需求)
我们经常需要按块下载数据。有时我们还需要能够处理不仅可以向后下载(例如,我们可以从不是从开始的地方开始加载),这样做时,我们通常必须解决相同的问题:防止重复加载同一页、防止页面加载冲突、保持加载状态并生成下一页/上一页的参数。分页器将解决其中大部分。
其主要组件包括
Paginator
本身 - 主入口点。连接所有其他部分。保持加载状态(是否正在进行任何方向的下载)分页参数提供程序
- 分页器状态的组成部分,被移动到分离的类别以提供更大的灵活性。它提供选定方向中的下一页的参数。这些参数取决于您要处理的服务器。最常用的参数提供程序(对于使用从到、限制偏移或 pageNumber-pageSize 坐标系的数据块的服务器)可以作为 Paginator/ParametersProviders
pod 或从 Classes/PagingParametersProviders
目录安装(如果您更喜欢手动安装)。Request Configuration Builder
我们使用不同的框架和库来执行网络请求,但它们都使用一些配置来描述请求(例如 NSURLRequest
)。PagingParametersProvider 只提供需要页面的参数字典,但你也可以添加其他参数、头部信息,并且可以使用任何类来描述请求。Request Configuration Builder 是放置你的请求描述构造器的地方。数据预处理块
- 此块将用于在返回给代理之前处理接收到的数据。如果服务器返回所需数据被包裹在某种字典中,或者如果您希望接收到映射到您内部数据类的结果,或者如果您需要执行数据转换以获取数据数组,这将非常有用。请求处理器
- 执行请求(通常是网络请求,但实际上这取决于您的处理器)。库不提供此组件,而只提供一个定义其要求的协议,因为具体的实现可能高度取决于应用程序架构和需求。所以,当您要求分页器下载下一页时,它
要使用分页器,首先需要像这样配置它(这看起来可能很长,但实际上这取决于您所工作的服务器)
// Create paging provider
AFPageNumberAndSizePagingParametersProvider *pagingProvider = [[AFPageNumberAndSizePagingParametersProvider alloc] initWithStartIndex:1];
pagingProvider.pageSize = 20;
pagingProvider.pageNumberParameterKey = @"page";
pagingProvider.pageSizeParameterKey = @"pagesize";
pagingProvider.numerationStartIndex = 1;
// Create the paginator itself
AFPaginator *dataLoader = [[AFPaginator alloc] initWithPagingParametersProvider:pagingProvider requestHandler:/*your custom handler*/];
// set configuration builder if needed
self.dataLoader.requestConfigurationBuilder = ^id _Nonnull(NSDictionary<NSString *,id> *pageParams) {
AFHTTPRequestConfiguration * result = [AFHTTPRequestConfiguration new];
result.baseURL = [NSURL URLWithString:@"URL string"];
result.requestPath = @"search";
result.parameters = pageParams;
return result;
};
// set preprocessing block if needed
dataLoader.dataPreprocessingBlock = ^NSArray *(id loadedData, NSError **error) {
if (error != NULL) {
*error = nil;
}
@try {
return [loadedData valueForKeyPath:@"items.title"];
} @catch (NSException *exception) {
if (error != NULL) {
*error = [NSError errorWithDomain:@"Domain" code:1000 userInfo:nil];
}
return nil;
}
};
// set delegate
self.dataLoader.delegate = self;
//then just save paginator object somewhere
或者用 Swift 的写法
// Create paging provider
let pagingProvider = PageNumberAndSizePagingParametersProvider(startIndex: 1)!
pagingProvider.pageSize = self.pageSize
pagingProvider.pageNumberParameterKey = "page"
pagingProvider.pageSizeParameterKey = "pagesize"
pagingProvider.numerationStartIndex = 1
// Create the paginator itself
let dataLoader = Paginator(pagingParametersProvider: pagingProvider, requestHandler: /*your custom handler*/)
// set configuration builder if needed
dataLoader.requestConfigurationBuilder = { pageParams -> HTTPRequestConfiguration in
return HTTPRequestConfiguration(baseUrl: URL(string: "URL string")!,
requestPath: "search",
parameters: pageParams)
}
// set preprocessing block if needed
self.dataLoader?.dataPreprocessingBlock = {
(sourceData, error) -> [Any]? in
error?.pointee = nil
guard let data = sourceData as? [String: Any],
let items = data["items"] as? [[String: Any]]
else {
error?.pointee = NSError(domain: "Paging error", code: 1000, userInfo: nil)
return nil
}
return items.flatMap { $0["title"] as? String }
}
// set delegate
dataLoader.delegate = self
//then just save paginator object somewhere
然后在您的代理中实现所需的方法,并调用 loadPageInDirection:
以开始加载。
有关如何使用的完整示例,请参阅示例。
Paginator 可在 MIT 许可证下使用。有关更多信息,请参阅 LICENSE 文件。