AFPaginator 1.0.2

AFPaginator 1.0.2

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最后发布2017年11月

Anton Filimonov 维护。



分页器

Version
License
Platform

这是一个小型库,简化了您的工作,允许您通过某些参数分块加载数据。它承担了分页数据加载的常见职责:防止对同一页面的多个请求、跟踪已加载数据范围、提供下一页/上一页参数。

示例

要运行示例项目,请克隆仓库,并首先在 Example 目录中运行 pod install。同样的方法,您可以在 ExampleSwift 目录中运行 Swift 示例项目。

要求

它应该可以正常工作在旧版本上,但在 Xcode 9.1 上在 iOS 8.4 及更高版本上进行了测试。

功能

  • Swift 兼容(所有类和方法名称都已转换为 Swift)
  • 100% 测试过
  • 高度灵活。自定义流程,提供所有依赖项的自己的实现
  • 完全文档化
  • CocoaPods 可安装

安装

CocoaPods

分页器通过 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 是放置你的请求描述构造器的地方。
  • 数据预处理块 - 此块将用于在返回给代理之前处理接收到的数据。如果服务器返回所需数据被包裹在某种字典中,或者如果您希望接收到映射到您内部数据类的结果,或者如果您需要执行数据转换以获取数据数组,这将非常有用。
  • 请求处理器 - 执行请求(通常是网络请求,但实际上这取决于您的处理器)。库不提供此组件,而只提供一个定义其要求的协议,因为具体的实现可能高度取决于应用程序架构和需求。

所以,当您要求分页器下载下一页时,它

  1. 从分页参数提供者获取页面的参数
  2. 使用请求配置构建器创建请求配置(如果没有设置构建器,则使用分页参数提供者返回的参数)
  3. 要求请求处理器执行请求
  4. 接收数据后,通过数据预处理块(如果已设置)处理它
  5. 通知分页参数提供者页面已加载,以让其更新其内部状态,为下一次加载做好准备
  6. 将加载的数据提供给其代理

使用方法

要使用分页器,首先需要像这样配置它(这看起来可能很长,但实际上这取决于您所工作的服务器)

// 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: 以开始加载。

有关如何使用的完整示例,请参阅示例。

作者

Anton Filimonov

许可证

Paginator 可在 MIT 许可证下使用。有关更多信息,请参阅 LICENSE 文件。