I have a class (WatchlistClass) that conforms to the "ObservableObject" protocol and that holds a @Published var (watchlist). The var, in turn, holds a whole array of stocks and some information ([StockInformation]), which is supposed to update my view (WatchlistView) with the current stock prices and stuff. That part works perfectly fine, but the class should access the @StateObject in the view to change the data. Accessing it directly in the class doesn't work because it doesn't read the data from the @StateObject. I tried to access the @StateObject in the view directly but that also creates a new instance of the class that has an empty array. Using "static" on a @Published var throws an error. I can't, for the life of me, figure out how to access a @StateObject directly inside the view to read and modify the data that it holds. Any help would be appreciated.
class WatchlistClass: ObservableObject {
static let shared = WatchlistClass()
@Published var watchlist: [StockInformation] = []
struct StockInformation: Identifiable {
...
}
func WatchlistTasksGetFundamentalsDelegate(string: String) {
...
DispatchQueue.main.async {
self.watchlist.append(stockInformation) // This works and updates the view as expected
}
...
}
private let timer = Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true) { _ in
if self.watchlist.isEmpty == false { // This does not work
...
}
}
struct WatchlistView: View {
@StateObject var watchlistClass = WatchlistClass()
...
}
Your timer
is an instance variable but its closure is not a instance of the class and has no self
.
You're going to have to do something to put "self" into the scope of the timer's block. One way to do that would be to create the timer in a member function of the instance:
private func makeTimer() -> Timer {
return Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true) { [weak self] _ in
if let empty = self?.watchlist.isEmpty,
empty == false {
}
}
}
When you call makeTimer() your code will be executing in the context of an instance. It will have access to a self
.
Note that I have changed your block so that it capture's self
"weakly" because the timer could exist beyond the life of the object so you have to be proactive against that possibility.
You could call makeTimer from your initializer.