【发布时间】:2022-11-07 18:48:13
【问题描述】:
我正在使用自定义 PullToRefresh 在用户需要时刷新整个屏幕。 PullToRefresh 执行特定操作,但在执行此操作时会冻结一秒钟。当我从刷新时执行的方法中删除 .sink 时,一切正常。
导致此错误的方法:
private func updateFitnessClasses() {
if let firstCompany = userCompanies.first {
updateFitnessClassesInteractor
.update(companyID: firstCompany.id)
.combineLatest(fitnessClassesRepository.fitnessClassesSections,
fitnessClassesRepository.calendarDayItems)
.replaceError(with: ((), [], []))
.sink(receiveValue: { [weak self] _, calendarSections, calendarRows in
self?.fitnessClassesSections = calendarSections
self?.calendarRows = calendarRows
})
.store(in: cancelBag)
}
}
其中fitnessClassesRepository.fitnessClassesSections 和fitnessClassesRepository.fitnessClassesSections 是在其他地方构建的AnyPublisher<[CalendarSection], Error>。我在另一种方法中使用这两个发布者,该方法在视图的.onAppear 中触发,并且 UI 不会在那里冻结。
同样UpdateFitnessClassesInteractor's.update() 看起来像这样:
func update(companyID: Int) -> AnyPublisher<Void, Error> {
fitnessClassCache
.lastUpdateTimestamp(forCompanyID: companyID)
.prefix(1)
.flatMap { self.apiClient.sendRequest(.fitnessClasses(timestamp: $0, companyID: companyID)) }
.map { $0.data }
.map { self.fitnessClassCache.updateCache(with: $0) }
.eraseToAnyPublisher()
}
有一个 API 调用,然后将新数据保存到数据库中,然后在 fitnessClassesRepository 方法中从中获取。
【问题讨论】:
-
尝试 .subscribe(on: backgroundQueue) .receive(on: RunLoop.main)
-
@SPatel 说 .subscribe(on: backgroundQueue) 你的意思是 .subscribe(on: DispatchQueue.global(qos: .background))?因为 XCode 告诉我没有“背景队列”之类的东西
-
是的,使用任何后台队列
-
@SPatel 好的。因此,
DispatchQueue.global(qos: .background))似乎可以完成这项工作,但是当我拉动以刷新我的应用程序时,由于Terminating app due to uncaught exception 'RLMException', reason: 'Realm accessed from incorrect thread.'错误而崩溃。因此,当我使用后台线程来使用 PullToRefresh 并且在执行的方法中有 Realm 操作时,如何安排 Realm 在同一个线程中执行所有操作? -
您可能需要使您的领域对象线程安全
标签: ios swift swiftui combine pull-to-refresh