Swift中API回调内更新@Published变量外部未生效问题求助
核心问题汇总
- 异步执行顺序问题:
Api().getPosts的回调是接口请求完成后才会执行,属于异步操作,而你写在闭包外的print代码会在loadData调用时立刻执行,此时接口还没返回,doesNotificationExist还停留在初始值false,这是正常逻辑,不是变量没有被更新。 @ObservedObject使用场景错误:该属性包装器仅适用于SwiftUI的View结构体,在非View类型的StatusBarController中使用时,不会自动监听@Published属性的变更,所以变量更新后不会触发UI刷新。- 队列问题:网络请求回调默认不在主队列,直接在回调中修改
@Published属性、后续触发UI更新时如果不在主队列执行,会导致UI不生效甚至崩溃。 - 单次赋值问题:你只在
StatusBarController的init方法中给状态栏按钮设置了一次图片,后续doesNotificationExist变更时没有主动更新按钮图片。
修正代码
1. 修正DataStore逻辑
替换原有loadData方法,修正捕获列表和队列问题:
func loadData() { Api().getPosts { [weak self] posts in guard let self = self else { return } // 所有@Published属性更新切换到主队列执行 DispatchQueue.main.async { self.posts = posts self.doesNotificationExist = posts.count >= 1 print("Api().getPosts") print(self.doesNotificationExist) } } // 这里打印的是接口请求前的初始值,为false是正常现象 print("loadData") print(doesNotificationExist) }
2. 修正StatusBarController监听逻辑
使用Combine手动监听属性变更,动态更新状态栏图片:
import AppKit import SwiftUI import Combine class StatusBarController { private var statusBar: NSStatusBar private var statusItem: NSStatusItem private var popover: NSPopover private let store = DataStore() // 存储订阅,避免被自动释放 private var cancellables = Set<AnyCancellable>() init(_ popover: NSPopover) { self.popover = popover statusBar = NSStatusBar.init() statusItem = statusBar.statusItem(withLength: 28.0) guard let statusBarButton = statusItem.button else { return } statusBarButton.action = #selector(togglePopover(sender:)) statusBarButton.target = self statusBarButton.image?.size = NSSize(width: 18.0, height: 18.0) statusBarButton.image?.isTemplate = true // 监听通知状态变更,动态更新图片 store.$doesNotificationExist .receive(on: DispatchQueue.main) .sink { [weak self] hasNotification in let imageName = hasNotification ? "StatusItemImageNotification" : "StatusItemImage" self?.statusItem.button?.image = NSImage(named: imageName) } .store(in: &cancellables) } // 其余原有代码保持不变 }
内容的提问来源于stack exchange,提问作者Niklas
相关产品推荐
相关产品推荐

