Last active
August 23, 2019 04:22
-
-
Save MasonRemaley/20cbb08260350517c746e84b5b707c36 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// # To test (macOS only) | |
// - Copy the contents of this file into a file called main.m | |
// - Run `clang main.m -fobjc-arc -xobjective-c++ -framework Cocoa && ./a.out` | |
// in bash | |
// - Send me: | |
// + The copy pasted console output from the run | |
// + Your macOS version (Apple > About This Mac) | |
// + Your clang version (`clang --version`) | |
// + Whether or not your computer has a Touch Bar | |
// | |
// # For The Curious | |
// I'm expecting the window I allocate to be subsequently be freed before exit, | |
// but on some computers, it is not. I suspect this is a bug in macOS as it | |
// seems like the extra retains are coming from AppKit & CoreFoundation, in | |
// something to do with the Touch Bar, but I'm not 100% positive. It's also | |
// possible I'm misunderstanding something fundamental about Objective-C memory | |
// management. | |
#import <Cocoa/Cocoa.h> | |
@interface Delegate: NSObject<NSWindowDelegate> | |
@end | |
@interface MyWindow: NSWindow | |
@end | |
int main() { | |
@autoreleasepool { | |
// Initialize the shared application | |
NSApplication* app = NSApplication.sharedApplication; | |
// Allow UI | |
app.activationPolicy = NSApplicationActivationPolicyRegular; | |
// Create the window and delegate | |
NSWindow *window = [[MyWindow alloc] init]; | |
Delegate *delegate = [[Delegate alloc] init]; | |
window.delegate = delegate; | |
// Have the window maintain normal refcount semantics | |
window.releasedWhenClosed = NO; | |
// Finish launching the app | |
[app finishLaunching]; | |
[NSRunningApplication.currentApplication | |
activateWithOptions:NSApplicationActivateAllWindows]; | |
// Show the window | |
[window orderFront:nil]; | |
// Simulate the user clicking the x (canceled by the delegate). If we | |
// comment out this line, or don't cancel the close in the delegate, we | |
// don't get the leak. | |
[window performClose:nil]; | |
// Actually close the window | |
[window close]; | |
} | |
NSLog(@"exit process"); | |
} | |
@implementation Delegate | |
- (instancetype)init { | |
NSLog(@"[delegate init]"); | |
return [super init]; | |
} | |
- (BOOL)windowShouldClose:(NSWindow *)sender { | |
NSLog(@"[delegate windowShouldClose:] (returning NO to cancel)"); | |
return NO; | |
} | |
- (void)windowWillClose:(NSNotification *)notification { | |
NSLog(@"[delegate windowWillClose:]"); | |
} | |
- (void)dealloc { | |
NSLog(@"[delegate dealloc]"); | |
} | |
@end | |
@implementation MyWindow | |
- (instancetype)init { | |
NSLog(@"[MyWindow init]"); | |
return [super | |
initWithContentRect:NSScreen.mainScreen.visibleFrame | |
styleMask:NSWindowStyleMaskTitled | | |
NSWindowStyleMaskClosable | | |
NSWindowStyleMaskMiniaturizable | | |
NSWindowStyleMaskResizable | |
backing:NSBackingStoreBuffered | |
defer:NO | |
]; | |
} | |
- (void)dealloc { | |
NSLog(@"[MyWindow dealloc]"); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment