ARTICLE AD BOX
I'm trying to develop a "simple" program to remind me to get up and walk around at least once an hour. I'm linking it to the Screen Lock, because either I Lock the screen when I get up, or it Locks when I'm away for five minutes. Much of this is working, but adding the cancellable notification popup is the sticking point. (Decades of programming experience but zero in swift, and vibe-coding isn't working out.) The part that isn't working is the creation, canceling, and recreation of a DispatchWorkItem to pop up the notification. It's coming down to scoping of the variable that holds the work item, and setting it, and closures and scoping and obscure swift rules.
NOTE: I am working on a High Sierra system that can not be updated, so more modern approaches and more modern syntax are off the table.
I had a version that at least compiled using "let" for reminderWorkItem inside of each block to make it compile. But of course then I didn't have the same variable scoped throughout the class, and cancelling doesn't work because it's not the same object. Since then I've been thrashing about with different variations on self or not self, and that sort of thing. This version fails to compile because reminderWorkItem isn't initialized and because where I try to initialize it on line 33 "'self' captured by a closure before all members were initialized".
I'm sure I'm misunderstanding some very basic concept.
import Foundation import AppKit extension Notification.Name { static let reminderDismissed = Notification.Name("ReminderDismissed") } class ScreenLockWatcher { var reminderWorkItem: DispatchWorkItem private func ShowReminder() { let alert = NSAlert() alert.messageText = "Take a break!" alert.informativeText = "Get up and go for a walk!!!" alert.alertStyle = .informational alert.addButton(withTitle: "OK") let response = alert.runModal() if response == .alertFirstButtonReturn { NSLog("dialog was dismissed") NotificationCenter.default.post( name: .reminderDismissed, object: nil ) } } init() { let dnc=DistributedNotificationCenter.default() reminderWorkItem = DispatchWorkItem { self.ShowReminder() } DispatchQueue.main.asyncAfter(deadline: .now()+3600.0, execute:self.reminderWorkItem) NSLog("Reminder queued") let _ = dnc.addObserver(forName: NSNotification.Name("com.apple.screenIsLocked"), object: nil, queue: .main) { _ in NSLog("Screen Locked") self.reminderWorkItem.cancel() NSLog("Reminder Cancelled") } let _ = dnc.addObserver(forName: NSNotification.Name("com.apple.screenIsUnlocked"), object: nil, queue: .main) { _ in NSLog("Screen UNLocked") self.reminderWorkItem = DispatchWorkItem { self.ShowReminder() } DispatchQueue.main.asyncAfter(deadline: .now()+3600.0, execute:self.reminderWorkItem) NSLog("Reminder queued") } let _ = NotificationCenter.default.addObserver(forName: .reminderDismissed, object: nil, queue: .main) { _ in NSLog("Reminder Dismissed") self.reminderWorkItem = DispatchWorkItem { self.ShowReminder() } DispatchQueue.main.asyncAfter(deadline: .now()+300.0, execute:self.reminderWorkItem) } RunLoop.main.run() } } let _ = ScreenLockWatcher()```