从视图外的函数访问@StateObject
Access @StateObject from function outside of view
我有一个 class (WatchlistClass),它符合“ObservableObject”协议并包含一个@Published var(监视列表)。 var 又包含一整套股票和一些信息 ([StockInformation]),这些信息应该用当前的股票价格和其他信息更新我的视图 (WatchlistView)。该部分工作得很好,但 class 应该访问视图中的 @StateObject 以更改数据。在 class 中直接访问它是行不通的,因为它不从 @StateObject 读取数据。我试图直接访问视图中的@StateObject,但这也创建了一个具有空数组的 class 的新实例。在 @Published var 上使用“static”会引发错误。在我的一生中,我无法弄清楚如何直接在视图内访问 @StateObject 以读取和修改它包含的数据。任何帮助将不胜感激。
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()
...
}
使用单例模式时,您通常希望在对象上声明 init
为私有对象,这样您就可以确定只能创建它的一个实例。
然后,要访问该单例版本,您将使用 WatchlistClass.shared
:
class WatchlistClass: ObservableObject {
static let shared = WatchlistClass()
@Published var watchlist: [StockInformation] = []
struct StockInformation: Identifiable {
//...
}
private init() { }
}
struct WatchlistView: View {
@StateObject var watchlistClass = WatchlistClass.shared
var body: some View {
//...
}
}
就您的 Timer
而言,在此处获得有关其服务目的的更多信息会很有帮助。例如,如果它只是检查 watchlist
以对其做出反应,我的建议是使用 Combine
来观看它而不是 Timer
.
如果单例版本的目的只是尝试访问 Timer
并使其能够访问数组,也许像这样的模式会更好:
import Combine
class WatchlistClass: ObservableObject {
@Published var watchlist: [StockInformation] = []
private var cancellable : AnyCancellable?
struct StockInformation: Identifiable {
var id = UUID()
//...
}
public init() {
cancellable = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.receive(on: RunLoop.main)
.sink { _ in
if !self.watchlist.isEmpty {
}
}
}
}
struct WatchlistView: View {
@StateObject var watchlistClass = WatchlistClass()
var body: some View {
Text("Hello, world!")
}
}
这将在 init
上创建 Timer
并授予它访问实例的 watchlist
数组的权限。
你的 timer
是一个实例变量,但它的闭包不是 class 的实例并且没有 self
.
您将不得不做一些事情来将“self”放入计时器块的范围内。一种方法是在实例的成员函数中创建计时器:
private func makeTimer() -> Timer {
return Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true) { [weak self] _ in
if let empty = self?.watchlist.isEmpty,
empty == false {
}
}
}
当您调用 makeTimer() 时,您的代码将在实例的上下文中执行。它将可以访问 self
.
请注意,我已经更改了您的块,以便它捕获 self
“弱”,因为计时器可能存在于对象的生命周期之外,因此您必须积极应对这种可能性。
您可以从初始化程序中调用 makeTimer。
我有一个 class (WatchlistClass),它符合“ObservableObject”协议并包含一个@Published var(监视列表)。 var 又包含一整套股票和一些信息 ([StockInformation]),这些信息应该用当前的股票价格和其他信息更新我的视图 (WatchlistView)。该部分工作得很好,但 class 应该访问视图中的 @StateObject 以更改数据。在 class 中直接访问它是行不通的,因为它不从 @StateObject 读取数据。我试图直接访问视图中的@StateObject,但这也创建了一个具有空数组的 class 的新实例。在 @Published var 上使用“static”会引发错误。在我的一生中,我无法弄清楚如何直接在视图内访问 @StateObject 以读取和修改它包含的数据。任何帮助将不胜感激。
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()
...
}
使用单例模式时,您通常希望在对象上声明 init
为私有对象,这样您就可以确定只能创建它的一个实例。
然后,要访问该单例版本,您将使用 WatchlistClass.shared
:
class WatchlistClass: ObservableObject {
static let shared = WatchlistClass()
@Published var watchlist: [StockInformation] = []
struct StockInformation: Identifiable {
//...
}
private init() { }
}
struct WatchlistView: View {
@StateObject var watchlistClass = WatchlistClass.shared
var body: some View {
//...
}
}
就您的 Timer
而言,在此处获得有关其服务目的的更多信息会很有帮助。例如,如果它只是检查 watchlist
以对其做出反应,我的建议是使用 Combine
来观看它而不是 Timer
.
如果单例版本的目的只是尝试访问 Timer
并使其能够访问数组,也许像这样的模式会更好:
import Combine
class WatchlistClass: ObservableObject {
@Published var watchlist: [StockInformation] = []
private var cancellable : AnyCancellable?
struct StockInformation: Identifiable {
var id = UUID()
//...
}
public init() {
cancellable = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.receive(on: RunLoop.main)
.sink { _ in
if !self.watchlist.isEmpty {
}
}
}
}
struct WatchlistView: View {
@StateObject var watchlistClass = WatchlistClass()
var body: some View {
Text("Hello, world!")
}
}
这将在 init
上创建 Timer
并授予它访问实例的 watchlist
数组的权限。
你的 timer
是一个实例变量,但它的闭包不是 class 的实例并且没有 self
.
您将不得不做一些事情来将“self”放入计时器块的范围内。一种方法是在实例的成员函数中创建计时器:
private func makeTimer() -> Timer {
return Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true) { [weak self] _ in
if let empty = self?.watchlist.isEmpty,
empty == false {
}
}
}
当您调用 makeTimer() 时,您的代码将在实例的上下文中执行。它将可以访问 self
.
请注意,我已经更改了您的块,以便它捕获 self
“弱”,因为计时器可能存在于对象的生命周期之外,因此您必须积极应对这种可能性。
您可以从初始化程序中调用 makeTimer。