我试图在执行一个blog请求时显示一个activity indicator。我所做的是创建一个ActivityTracker对象,它将跟踪发布者的生命周期。这个ActivityTracker是一个ObservableObject,将存储在视图模型中,视图模型也是一个ObservableObject。
看起来这种设置并没有刷新视图。下面是我的代码:
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
,但结果相同,我的文本没有更新。请注意,将Activity Tracker直接存储在视图中也可以,但这不是我想要的。
我错过什么了吗?
2条答案
按热度按时间ewm0tg9j1#
目前还不支持嵌套的ObservableObjects。当你想使用这些嵌套对象时,你需要在数据发生变化时自己通知对象。我希望下面的代码可以帮助你解决这个问题。
首先用途:
import Combine
然后声明你的模型和子模型,它们都需要使用
@ObservableObject
属性来工作。(不要忘记@Published
属性)我做了一个父模型,名为Model和两个子模型Submodel 1 & Submodel 2。当你在修改数据时使用父模型时,例如:
model.submodel1.count
,你需要使用一个通知程序,以便让视图自动更新。AnyCancellables通知父模型本身,在这种情况下,View将自动更新。
复制代码并自己使用它,然后尝试在使用此代码时重新制作您的代码。希望这对您有帮助,祝您好运!
字符串
当你想使用这个Model时,就像正常使用ObservedObjects一样使用它。
型
dphi5xsq2#
如果你有一个收藏品,你可以这样做:
字符串