SKBatcher 0.0.5

SKBatcher 0.0.5

测试已测试
Lang语言 SwiftSwift
许可证 MIT
Released最后一次发布2017年2月
SwiftSwift 版本3.0
SPM支持 SPM

Scott J. Kleper 维护。



SKBatcher 0.0.5

  • Scott J. Kleper

为 UITableView 或其他渐进式加载控制器批量加载内容。

  1. 它能如何帮助我?
  2. 需求
  3. 集成
  4. 使用
  5. 状态和下一步操作

它能如何帮助我?

最好的方式是通过一个例子来了解。在 AngelList Jobs App 中,我们有一个消息功能,允许求职者与应聘者沟通。它是一个非常标准的聊天 UI -- 你可以看到在 UITableView 中的对话列表,你可以点击其中一个来查看聊天消息

Chat UI

加载列表是有技巧的。用户可能有成千上万的对话。获取另一个用户的头像和最新消息的摘录是昂贵的操作。我们想让表格尽可能快地加载和滚动,但我们不希望从服务器返回大量我们可能甚至不需要的数据包。

SKBatcher 让高效加载视图部分变得超级简单。由于 UITableView 拥有智能功能,只有在需要时才加载单元格,我们可以只在需要时访问服务器。在我们的例子中,对话列表是通过单个查询获取的,但摘录和头像在后台进行,仅当需要时。

  1. SKBatcher 在 iOS 告诉我们需要显示时,加载对话的辅助数据

  2. 批量组合请求,以免向服务器发送大量小的请求。

  3. 跟踪未完成的请求,以免在重复请求上浪费时间。

  4. 缓存结果,以便如果用户向下滚动再向上滚动,我们不需要再次击中服务器。

需求

  • iOS 8.0+
  • Xcode 8
  • Swift 2.3

依赖

  • SwiftyJSON ~> 2.3.3

集成

使用

  1. 创建 SKBatcher 将使用的函数

您需要一个 SKBatcher 可以用来获取一系列 ID 的结果的函数。这通常是类似以下示例的服务器调用,使用 Alamofire,但它可以是任何符合预期函数签名的东西

    func getConversationExcerpts(ids: [Int], completion: (JSON?) -> Void) {
        request("GET", path: "/excerpts", parameters: ["ids": ids], encoding: .URL).responseData { response in
            if let results = response.result.value {
                completion(JSON(data: results))
            } else {
                completion(nil)
            }
        }
    }

您的函数将需要两个参数 -- 一个表示 id 的 Int 数组和一个完成处理器,它接收一个可选的 JSON。假设 anyone 能理解 Swift 闭包声明的语法,它应该是这样的

    (([Int], ((JSON?) -> Void)) -> Void)

为了明确起见,你在代码中编写一个符合该规定的函数,它可以完成你想要的功能。JSON结果应该将ID映射到你想要的内容,例如:

{ "1"=>"This is the content for id 1",
  "2"=>"This is the content for id 2"
}
  1. 为该函数创建一个批处理器并填充它
import SKBatcher

class ConversationTableViewController : UITableViewController {

    var excerptBatcher: SKBatcher

    override func viewDidLoad() {
        super.viewDidLoad()

        excerptBatcher = SKBatcher(apiCall: APICalls.getConversationExcerpts)
    }
}

当我们有了ID列表时,设置批处理器

func setIds(ids: [Int]) {
    avatarBatcher.allIds = ids
    tableView.reloadData()
}
  1. 当你需要一个UITableViewCell,将其作为SKBatcher填充时
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let conversationId = conversationIdForIndexPath(indexPath)

        var cell = tableView.dequeueReusableCellWithIdentifier(MyCell.identifier, forIndexPath: indexPath) as? MyCell
        if cell == nil {
            cell = MyCell(identifier: MyCell.identifier)
        }
        cell?.id = conversationId

        // Load avatars from batcher
        cell?.excerpt = "" // Initialize excerpt to empty while it's loading
        exerptBatcher.fetch(conversationId) { excerpt in 
            // Now we have the excerpt. Make sure the cell hasn't been reused and set it
            if (cell?.id == conversationId) {
                cell?.excerpt = (excerpt as? String)
            }
        } 

就这样!SKBatcher会负责启动ID的请求,并缓存结果。它通常会简化生活。

状态和下一步

tôi đã viết SKBatcher cho trường hợp ứng dụng mô tả trên - liệt kê một số lượng lớn các cuộc trò chuyện trong UITableView . Trong quá trình viết, tôi nhận ra rằng nó tự nhiên trở thành điều gì đó thông dụng và có thể tái sử dụng. Tôi vẫn chưa đầu tư nhiều nỗ lực để làm cho nó thực sự có thể tái sử dụng. Tuyệt đối, nó sẽ có thêm cấu hình và linh hoạt hơn với định dạng đầu vào và đầu ra. Tôi cũng muốn dành thời gian để tạo một ví dụ tốt hơn với mã có thể chạy.

Nguy cơ tiềm ẩn

  • Tôi vẫn chưa suy nghĩ nhiều về an toàn về luồng, mặc dù tôi tin rằng không phải là một vấn đề
  • Có thể có chu kỳ duy trì do sử dụng b annoncé closures
  • Tôi chưa viết các bài kiểm tra để xác minh rằng quá trình lưu cache và preload diễn ra đúng cách