我正在尝试执行异步请求时显示活动指示器。 我所做的是创建一个activityTracker对象,该对象将跟踪发布者的生命周期。 此activityTracker是一个ObservableObject,将存储在也是ObservableObject的视图模型中。
似乎这种设置并没有刷新View。这是我的代码:
struct ContentView: View {
@ObservedObject var viewModel = ContentViewModel()
var body: some View {
VStack(spacing: 16) {
Text("Counter: \(viewModel.tracker.count)\nPerforming: \(viewModel.tracker.isPerformingactivity ? "true" : "false")")
Button(action: {
_ = request().trackactivity(self.viewModel.tracker).sink { }
}) {
Text("Request")
}
}
}
}
class ContentViewModel: ObservableObject {
@Published var tracker = Publishers.activityTracker()
}
private func request() -> AnyPublisher<Void,Never> {
return Just(()).delay(for: 2.0,scheduler: RunLoop.main)
.eraseToAnyPublisher()
}
extension Publishers {
final class activityTracker: ObservableObject {
// MARK: Properties
@Published var count: Int = 0
var isPerformingactivity: Bool {
return count > 0
}
private var cancellables: [AnyCancellable] = []
private let counterSubject = CurrentvalueSubject<Int,Never>(0)
private let lock: NSRecursiveLock = .init()
init() {
counterSubject.removeDuplicates()
.receive(on: RunLoop.main)
.print()
.sink { [weak self] counter in
self?.count = counter
}
.store(in: &cancellables)
}
// MARK: Private methods
fileprivate func trackactivity<Value,Error: Swift.Error>(
ofPublisher publisher: AnyPublisher<Value,Error>
) {
publisher
.receive(on: RunLoop.main)
.handleEvents(
receiveSubscription: { _ in self.increment() },receiveOutput: nil,receiveCompletion: { _ in self.decrement() },receiveCancel: { self.decrement() },receiveRequest: nil
)
.print()
.sink(receiveCompletion: { _ in },receiveValue: { _ in })
.store(in: &cancellables)
}
private func increment() {
lock.lock()
defer { lock.unlock() }
counterSubject.value += 1
}
private func decrement() {
lock.lock()
defer { lock.unlock() }
counterSubject.value -= 1
}
}
}
extension AnyPublisher {
func trackactivity(_ activityTracker: Publishers.activityTracker) -> AnyPublisher {
activityTracker.trackactivity(ofPublisher: self)
return self
}
}
我还尝试将activityTracker声明为@Published
,但结果相同,我的文本未更新。
请注意,将活动跟踪器直接存储在视图中将起作用,但这不是我想要的。
我在这里错过了什么吗?