macos - 我在 SwiftUI 中的 macOS 应用程序,定时器在窗口 (NSWindow) 关闭后永不停止

标签 macos timer swiftui nswindow

我在 View 中使用计时器来显示时间。在 View 的 onAppear() 和 onDisappear() 方法中,Timer 运行良好。

但是当我关闭窗口时,似乎没有调用 onDisappear() 方法,并且 Timer 永远不会停止。

这是我的测试代码:

import SwiftUI
    
struct TimerTest: View {
    @State var date = Date()
    @State var showSubView = false
    @State var timer: Timer?
    
    var body: some View {
        ZStack{
            if showSubView {
                VStack {
                    Text(" Timer Stoped?")
                    Button("Back") {
                        self.showSubView = false
                    }
                }
            }
            else {
                VStack {
                    Button("Switch to subview"){
                        self.showSubView = true
                    }

                    Text("date: \(date)")
                        .onAppear(perform: {
                            self.timer = Timer.scheduledTimer(withTimeInterval: 1,
                                            repeats: true,
                                            block: {_ in
                                              self.date = Date()
                                              NSLog("🔷onAppear timer triggered")
                                             })
                        })
                        .onDisappear(perform: {
                            self.timer?.invalidate()
                            self.timer = nil
                            NSLog("🔶 onDisappear stop timer")
                            // But if I close window, this method never be called
                        })
                }
            }
        }
        .frame(width: 500, height: 300)
    }
}
  1. 那么,在窗口关闭后应该如何正确停止定时器呢?

  2. 以及如何在窗口关闭时通知View,旨在释放View实例中的一些资源。

(我想出了一个使用 TimerPublisher 替换 Timer 的技巧方法,它会在窗口关闭后自动停止。但这并不能解决我的困惑。)

最佳答案

使用 .hostingWindow 环境(来自 How to access own window within SwiftUI view? )可以使用以下方法。

使用 Xcode 11.4/iOS 13.4 测试

struct TimerTest: View {
    @Environment(\.hostingWindow) var myWindow
    @State var date = Date()
    @State var showSubView = false
    @State var timer: Timer?

    var body: some View {
        ZStack{
            if showSubView {
                VStack {
                    Text(" Timer Stoped?")
                    Button("Back") {
                        self.showSubView = false
                    }
                }
            }
            else {
                VStack {
                    Button("Switch to subview"){
                        self.showSubView = true
                    }

                    Text("date: \(date)")
                        .onAppear(perform: {
                            self.timer = Timer.scheduledTimer(withTimeInterval: 1,
                                            repeats: true,
                                            block: {_ in
                                              self.date = Date()
                                              NSLog("🔷onAppear timer triggered")
                                             })
                        })
                        .onDisappear(perform: {
                            self.timer?.invalidate()
                            self.timer = nil
                            NSLog("🔶 onDisappear stop timer")
                            // But if I close window, this method never be called
                        })
                }
                .onReceive(NotificationCenter.default.publisher(for: NSWindow.willCloseNotification, object: myWindow())) { _ in
                    self.timer?.invalidate()
                    self.timer = nil
                }
            }
        }
        .frame(width: 500, height: 300)
    }
}

关于macos - 我在 SwiftUI 中的 macOS 应用程序,定时器在窗口 (NSWindow) 关闭后永不停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63231591/

相关文章:

node.js - 找不到 SLC 命令

c++ - boost 截止时间计时器的替代方案

ios - 如何在框架中使用 SwiftUI

SwiftUI:点击即可获取 View 的框架?

ios - 如何使用 swiftui 设计具有半径部分的表单

java - Oracle 的 Java 7 for Mac OS X 是否有 com.apple.eawt.CocoaComponent 或类似组件?

xcode - 实现 NSService 方法

PHP:如何在不使用 AJAX 调用的情况下更新用户登录计时器

macos - 如何在终端中使用vim?

flutter - 如何在 Flutter 中一段时间​​不活动后执行函数