使用RxSwift进行分页API调用

前端之家收集整理的这篇文章主要介绍了使用RxSwift进行分页API调用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在为iOS应用程序开始我的第一个Rx Swift项目并学习反应式编程.

到目前为止,这个想法非常简单,用户搜索搜索栏文本匹配的电影,这会触发一个请求,用UfuableView填充结果.使用在线发现的教程和示例,我已经设法实现了这一点而没有太多麻烦.

当我试图加载通过滚动表格视图底部触发的下一页结果时,棘手的部分就出现了.

这是到目前为止使用的代码

public final class Homeviewmodel: NSObject {

    // MARK: - Properties

    var searchText: Variable<String> = Variable("")
    var loadNextPage: Variable<Void> = Variable()

    lazy var pages: Observable<PaginatedList<Film>> = self.setupPages()

    // MARK: - Reactive Setup

    fileprivate func setupPages() -> Observable<PaginatedList<Film>> {
        return self.searchText
            .asObservable()
            .debounce(0.3,scheduler: MainScheduler.instance)
            .distinctUntilChanged()
            .flatMapLatest { (query) -> Observable<PaginatedList<Film>> in
                return TMDbAPI.Films(withTitle: query,atPage: 0)
            }
            .shareReplay(1)
    }
}

这是我到目前为止:可观察的页面绑定到HomeViewController中的表视图,其搜索栏文本绑定到searchText.

我正在使用Alamofire在幕后执行API调用,TMDbAPI.Films(withTitle:query)返回一个Observable的分页列表.

这是我的模型结构PaginatedList

public struct PaginatedList<T> {

    // MARK: - Properties

    let page: Int
    let totalResults: Int
    let totalPages: Int
    let results: [T]

    // MARK: - Initializer

    init(page: Int,totalResults: Int,totalPages: Int,results: [T]) {
        self.page = page
        self.totalResults = totalResults
        self.totalPages = totalPages
        self.results = results
    }

    // MARK: - Helper functions / properties

    var count: Int { return self.results.count }

    var nextPage: Int? {
        let nextPage = self.page + 1
        guard nextPage < self.totalPages else { return nil }
        return nextPage
    }

    static func Empty() -> PaginatedList { return PaginatedList(page: 0,totalResults: 0,totalPages: 0,results: []) }
}

extension PaginatedList {

    // MARK: - Subscript

    subscript(index: Int) -> T {
        return self.results[index]
    }
}

我现在正在寻找一种反应方式来将我的loadNextPage变量挂钩到分页列表的observable,它会触发对下一页的请求.
搜索栏文本发生变化时,它会将分页重置为0.

我相信需要使用运算符扫描和连接,但我仍然不确定如何…

如何实现这一点的任何建议将非常感谢…

这是你如何构建它:
// Some kind of page request result.  Modify it to be what you're using.

struct SomePageResult {
    let content: String
}

// Needs modification to return your actual data

func getPage(query: String,number: UInt) -> SomePageResult {
    return SomePageResult(content: "some content for search (\(query)) on page \(number)")
}

// Actual implementation

let disposeBag = DisposeBag()

var loadNextPage = PublishSubject<Void>()
var searchText = PublishSubject<String>()
let currentPage = searchText
    .distinctUntilChanged()
    .flatMapLatest { searchText in
        return loadNextPage.asObservable()
            .startWith(())
            .scan(0) { (pageNumber,_) -> UInt in
                pageNumber + 1
            }
            .map { pageNumber in
                (searchText,pageNumber)
            }
    }
    .map { (searchText,pageNumber) in
        getPage(searchText,number: pageNumber)
    }

currentPage
    .subscribeNext { print($0) }
    .addDisposableTo(disposeBag)

searchText.onNext("zebra")
searchText.onNext("helicopter")
loadNextPage.onNext()
searchText.onNext("unicorn")
searchText.onNext("unicorn")
searchText.onNext("ant")
loadNextPage.onNext()
loadNextPage.onNext()
loadNextPage.onNext()

输出

SomePageResult(content: “some content for search (zebra) on page 1”) SomePageResult(content: “some content for search (helicopter) on page 1”) SomePageResult(content: “some content for search (helicopter) on page 2”) SomePageResult(content: “some content for search (unicorn) on page 1”) SomePageResult(content: “some content for search (ant) on page 1”) SomePageResult(content: “some content for search (ant) on page 2”) SomePageResult(content: “some content for search (ant) on page 3”) SomePageResult(content: “some content for search (ant) on page 4”)

猜你在找的Swift相关文章