SwiftUI:popover.show 后重新初始化

Posted

技术标签:

【中文标题】SwiftUI:popover.show 后重新初始化【英文标题】:SwiftUI: Reinitialize after popover.show 【发布时间】:2020-10-11 05:07:00 【问题描述】:

我正在使用弹出框编写 MacOS (10.15 Catalina) 应用程序。主 ContentView 包含一个带有简单切换的自定义视图:

class AppDelegate: NSObject, NSApplicationDelegate 
    var popover=NSPopover()
    func applicationDidFinishLaunching(_ aNotification: Notification) 
        self.popover.contentViewController = NSHostingController(rootView: contentView)

        self.statusBarItem = NSStatusBar.system.statusItem(withLength: 18)
        
        if let statusBarButton = self.statusBarItem.button 
            statusBarButton.title = "☰"
            statusBarButton.action = #selector(togglePopover(_:))
        

    func show() 
        let statusBarButton=self.statusBarItem.button!
        self.popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: NSRectEdge.maxY)
    
    func hide() 
        popover.performClose(nil)
    
    @objc func togglePopover(_ sender: AnyObject?) 
        self.popover.isShown ? hide() : show()
    


struct ContentView: View 
    var body: some View 
        Test("Hello")
        //  more stuff
    


struct Test: View 
    var message: String
    @State private var clicked: Bool = false

    init(message: String) 
        self.message = message
        _clicked = State(initialValue: false)
        print("init")
    

    var body: some View 
        return HStack 
            Text(message)
            Button("Click") 
                self.clicked = true
            
            if !self.clicked 
                Text("Before")
            
            else 
                Text("After")
            
        
    

每当弹出窗口再次出现时,我想在自定义视图中重新初始化一些数据。因此,在本例中,clicked 应重置为 false。我已经尝试了@Binding@State 变量的所有组合,我可以在许多搜索中找到,但似乎没有任何效果。 .onAppear() 似乎只在第一次触发。

init() 函数之所以存在,是因为在我的应用程序中我还需要包含其他内容和代码。在此示例中,我尝试使用它来初始化 clicked 状态变量,但是,虽然 print() 函数确实打印,但变量似乎没有被重置。

如何重新初始化@State 变量?

【问题讨论】:

【参考方案1】:

要在 init 中初始化状态,您不应该将其初始化为属性(因为属性在 init 之前初始化并且状态只初始化一次),所以

struct Test: View 
    var message: String
    @State private var clicked: Bool     // << here, only declare

    init(message: String) 
        self.message = message
        _clicked = State(initialValue: false)   // << then this works
        print("init")
    
    
    // ... other code

【讨论】:

谢谢,但我仍然发现clicked 似乎是true,因为After 文字在第一次之后仍然显示。 不清楚您需要在哪个时刻(或在哪个事件)重置clicked,因此缺少代码 - 您能澄清一下吗? 我已经包含了一个非常简短的 AppDelegate 版本。这个想法是当我再次显示弹出窗口时,Test 视图应该被重置。 尝试用Test("Hello").id(UUID())重新创建它 成功了。我可以猜到那里发生了什么,但这是一个肮脏的把戏吗?是否可以将该技巧合并到 Test 视图中,使其独立存在?

以上是关于SwiftUI:popover.show 后重新初始化的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI初感悟与感想

SwiftUI初感悟与感想

列表重新排序后 SwiftUI 关闭

SwiftUI:取消定时器后如何重新启动它?

SwiftUI 模式表在关闭后重新打开

重新排序列表部分 SwiftUI