Skip to content

Instantly share code, notes, and snippets.

@lunacookies
Created May 7, 2025 06:39
Show Gist options
  • Select an option

  • Save lunacookies/e9ce5bb2117d4fe0224fa9996ef9645f to your computer and use it in GitHub Desktop.

Select an option

Save lunacookies/e9ce5bb2117d4fe0224fa9996ef9645f to your computer and use it in GitHub Desktop.
Combining view controller lifecycle methods and window occlusion notifications to pause invisible work
@import AppKit;
@import os.log;
@interface MainViewController : NSViewController
@end
@implementation MainViewController {
NSTextField *_label;
id<NSObject> _occlusionObserver;
NSTimer *_timer;
}
- (void)loadView {
[super loadView];
_label = [NSTextField labelWithString:@"hello world"];
_label.translatesAutoresizingMaskIntoConstraints = NO;
NSView *view = self.view;
[view addSubview:_label];
[NSLayoutConstraint activateConstraints:@[
[_label.centerXAnchor constraintEqualToAnchor:view.centerXAnchor],
[_label.centerYAnchor constraintEqualToAnchor:view.centerYAnchor],
[_label.leadingAnchor constraintGreaterThanOrEqualToAnchor:view.leadingAnchor],
[_label.trailingAnchor constraintLessThanOrEqualToAnchor:view.trailingAnchor],
]];
}
- (void)viewWillAppear {
[super viewWillAppear];
os_log_debug(OS_LOG_DEFAULT, "viewWillAppear");
[self viewBecameVisible];
}
- (void)viewDidAppear {
[super viewDidAppear];
os_log_debug(OS_LOG_DEFAULT, "viewDidAppear");
if (_occlusionObserver == nil) {
NSWindow *window = self.view.window;
_occlusionObserver = [NSNotificationCenter.defaultCenter
addObserverForName:NSWindowDidChangeOcclusionStateNotification
object:window
queue:nil
usingBlock:^(NSNotification *notification) {
if (window.occlusionState & NSWindowOcclusionStateVisible) {
os_log_debug(OS_LOG_DEFAULT, "window became visible");
[self viewBecameVisible];
} else {
os_log_debug(OS_LOG_DEFAULT, "window became hidden");
[self viewBecameHidden];
}
}];
}
}
- (void)viewWillDisappear {
[super viewWillDisappear];
os_log_debug(OS_LOG_DEFAULT, "viewWillDisappear");
}
- (void)viewDidDisappear {
[super viewDidDisappear];
os_log_debug(OS_LOG_DEFAULT, "viewDidDisappear");
[self viewBecameHidden];
[NSNotificationCenter.defaultCenter removeObserver:_occlusionObserver];
_occlusionObserver = nil;
}
- (void)dealloc {
os_log_debug(OS_LOG_DEFAULT, "=== DEALLOC ===");
}
- (void)viewBecameVisible {
dispatch_assert_queue(dispatch_get_main_queue());
[self updateLabel];
if (_timer == nil) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.1
repeats:YES
block:^(NSTimer *timer) {
[self updateLabel];
}];
os_log_debug(OS_LOG_DEFAULT, "started timer");
}
}
- (void)viewBecameHidden {
dispatch_assert_queue(dispatch_get_main_queue());
if (_timer != nil) {
os_log_debug(OS_LOG_DEFAULT, "stopping timer %@...", _timer);
[_timer invalidate];
_timer = nil;
os_log_debug(OS_LOG_DEFAULT, "stopped timer");
}
}
- (void)updateLabel {
dispatch_assert_queue(dispatch_get_main_queue());
os_log_debug(OS_LOG_DEFAULT, "update label");
_label.stringValue = [NSDate date].description;
}
@end
@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>
@end
@implementation AppDelegate {
NSWindow *_window;
}
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender {
_window = [NSWindow windowWithContentViewController:[[MainViewController alloc] init]];
_window.delegate = self;
[_window makeKeyAndOrderFront:nil];
return YES;
}
- (void)windowWillClose:(NSNotification *)notification {
_window = nil;
}
@end
int main(void) {
[NSApplication sharedApplication];
NSApp.activationPolicy = NSApplicationActivationPolicyRegular;
AppDelegate *appDelegate = [[AppDelegate alloc] init];
NSApp.delegate = appDelegate;
[NSApp run];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment