首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用RxSwift定期调用API

使用RxSwift定期调用API
EN

Stack Overflow用户
提问于 2018-09-13 10:39:25
回答 2查看 4.5K关注 0票数 4

我试图定期(每10秒)调用一个返回模型的Json对象的API:

代码语言:javascript
运行
复制
struct MyModel { 
   var messagesCount: Int?
   var likesCount: Int?
}

如果messageCountlikesCount值发生更改,则更新UI。我尝试了计时器解决方案,但我发现它有点混乱,我想要一个更干净的解决方案与RxSwift和RxAlamofire。

任何帮助都是非常感谢的,因为我是Rx的新手。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-13 12:31:22

欢迎来到StackOverflow!

这需要相当多的操作符,我建议在ReactiveX运算符页上查找它们,每次我忘记一些东西时都会检查它。

首先,确保MyModel符合Decodable,这样就可以从JSON响应构建它(参见可编)。

代码语言:javascript
运行
复制
let willEnterForegroundNotification = NotificationCenter.default.rx.notification(.UIApplicationWillEnterForeground)
let didEnterBackgroundNotification = NotificationCenter.default.rx.notification(.UIApplicationDidEnterBackground)

let myModelObservable = BehaviorRelay<MyModel?>(value: nil)

willEnterForegroundNotification
    // discard the notification object
    .map { _ in () }
    // emit an initial element to trigger the timer immediately upon subscription
    .startWith(())
    .flatMap { _ in 
        // create an interval timer which stops emitting when the app goes to the background
        return Observable<Int>.interval(10, scheduler: MainScheduler.instance)
            .takeUntil(didEnterBackgroundNotification)
    }
    .flatMapLatest { _ in 
        return RxAlamofire.requestData(.get, yourUrl)
            // get Data object from emitted tuple
            .map { $0.1 } 
            // ignore any network errors, otherwise the entire subscription is disposed
            .catchError { _ in .empty() } 
    } 
    // leverage Codable to turn Data into MyModel
    .map { try? JSONDecoder().decode(MyModel.self, from: $0) } }
    // operator from RxOptional to turn MyModel? into MyModel
    .filterNil() 
    .bind(to: myModelObservable)
    .disposed(by: disposeBag)

然后,您可以继续数据流到您的UI元素。

代码语言:javascript
运行
复制
myModelObservable
    .map { $0.messagesCount }
    .map { "\($0) messages" }
    .bind(to: yourLabel.rx.text }
    .disposed(by: disposeBag)

我没有运行这段代码,所以这里可能有一些输入/缺少转换,但这应该会指向正确的方向。请随时要求澄清。如果Rx是真正的新手,我建议您通过入门指南。太棒了!Rx非常强大,但我花了一段时间才掌握。

编辑

正如@daniel所指出的,在使用Observable<Int>.interval时,后台/前台簿记是不必要的。

票数 8
EN

Stack Overflow用户

发布于 2018-09-13 23:55:18

CloakedEddy与他的回答非常接近,理应得到更多选票。然而,他把事情弄得比必要的复杂一些。Interval在内部使用DispatchSourceTimer,当应用程序转到后台并返回到前台时,它将自动停止并重新启动。他也做了一个伟大的工作,记得抓住错误,以阻止河流松开。

我假设下面的代码在AppDelegate或高级协调员中。另外,myModelSubject是一个ReplaySubject<MyModel> (用:ReplaySubject<MyModel>.create(bufferSize: 1)创建它,它应该放在视图控制器可以访问或传递给视图控制器的地方)。

代码语言:javascript
运行
复制
Observable<Int>.interval(10, scheduler: MainScheduler.instance) // fire at 10 second intervals.
    .flatMapLatest { _ in
        RxAlamofire.requestData(.get, yourUrl) // get data from the server.
            .catchError { _ in .empty() }   // don't let error escape.
    }
    .map { $0.1 } // this assumes that alamofire returns `(URLResponse, Data)`. All we want is the data.
    .map { try? JSONDecoder().decode(MyModel.self, from: $0) } // this assumes that MyModel is Decodable
    .filter { $0 != nil } // filter out nil values
    .map { $0! } // now that we know it's not nil, unwrap it.
    .bind(to: myModelSubject) // store the value in a global subject that view controllers can subscribe to.
    .disposed(by: bag) // always clean up after yourself.
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52311965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档