You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 19:15:01