Disable Autolayout for NSSplitView in Interface Builder - cocoa

By using a NSSplitViewController inside my Storyboard, I wanted to override the behaviour of the contained split view.
By implementing some of the the NSSplitViewDelegate method regarding the max constraint for the slider, I got this exception raised:
2017-01-12 11:05:45.873814 iCache[3399:659731] [General] SplitViewController's splitView is unable to use autolayout because the SplitViewController overrides an incompatible delegate method.
2017-01-12 11:05:45.874089 iCache[3399:659731] [General] (
0 CoreFoundation 0x00007fffb5d9ee7b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00007fffca989cad objc_exception_throw + 48
2 CoreFoundation 0x00007fffb5da3b82 +[NSException raise:format:arguments:] + 98
3 Foundation 0x00007fffb77edd50 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
4 AppKit 0x00007fffb389ca29 -[NSSplitView _splitViewUseConstraintBasedLayout] + 355
5 AppKit 0x00007fffb389c894 -[NSSplitView(NSSplitViewDividerViews) _canUseDividerViewsAsSubviews] + 74
6 AppKit 0x00007fffb389c0f7 -[NSSplitView(NSSplitViewDividerViews) _updateDividerViews] + 36
7 AppKit 0x00007fffb389dd41 -[NSSplitViewController _updateSplitView:withBlock:] + 51
8 AppKit 0x00007fffb389dc89 -[NSSplitViewController viewDidLoad] + 144
9 AppKit 0x00007fffb3896283 -[NSViewController _sendViewDidLoad] + 97
10 CoreFoundation 0x00007fffb5d17889 -[NSSet makeObjectsPerformSelector:] + 217
11 AppKit 0x00007fffb3814902 -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 1389
12 AppKit 0x00007fffb391d436 -[NSNib _instantiateNibWithExternalNameTable:options:] + 696
13 AppKit 0x00007fffb391d06a -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 143
14 AppKit 0x00007fffb403f34a -[NSStoryboard instantiateControllerWithIdentifier:] + 234
15 AppKit 0x00007fffb3805bb7 NSApplicationMain + 780
16 iCache 0x00000001000127f4 main + 84
17 libdyld.dylib 0x00007fffcb26d255 start + 1
)
Apparently this is due to to Autolayout used for the split view.
Is there a way to disable Autolayout for this NSSplitView inside Interface Builder?

Enable/disable Auto Layout
You can disable Auto Layout per XIB file in the Interface Builder under File Inspector.
You should be able to control autolayout per view through the views translatesAutoresizingMaskIntoConstraints.
Why it doesn't work
According to OS X 10.11 release notes there are some methods you cannot use in combination with autolayout.
Please see this excerption from the notes.
Auto Layout NSSplitView improvements
In 10.8, NSSplitView properly respects constraints applied to its subviews, such as their minimum view widths. There are also new APIs for controlling the holding priorities, which determine both the NSLayoutPriority at which a split view holds its sizes and also which views change size if the split view itself grows or shrinks.
(NSLayoutPriority)holdingPriorityForSubviewAtIndex:(NSInteger)subviewIndex;
(void)setHoldingPriority:(NSLayoutPriority)priority forSubviewAtIndex:(NSInteger)subviewIndex;
In order to take advantage of these improvements, you must NOT implement any of the following NSSplitViewDelegate methods:
splitView:constrainMinCoordinate:ofSubviewAt:
splitView:constrainMaxCoordinate:ofSubviewAt:
splitView:resizeSubviewsWithOldSize:
splitView:shouldAdjustSizeOfSubview:
These methods are incompatible with auto layout. You can typically achieve their effects and more with auto layout.

Related

How to update an NSTextView while user is scrolling (without crashing)

I'm using an NSTextView to display the result of a long search, where lines are added as they are found by a background thread using
[self performSelectorOnMainThread: #selector(addMatch:)
withObject:options waitUntilDone:TRUE];
As the update routine I have
-(void)addMatch:(NSDictionary*)options{
...
NSTextStorage* store = [textView textStorage];
[store beginEditing];
[store appendAttributedString:text];
...
[store endEditing];
}
This works fine, until the user scrolls through the matches as they are being updated, at which point there's an exception
-[NSLayoutManager _fillLayoutHoleForCharacterRange:desiredNumberOfLines:isSoft:] *** attempted layout while textStorage is editing. It is not valid to
cause the layoutManager to do layout while the textStorage is editing
(ie the textStorage has been sent a beginEditing message without a
matching endEditing.)
within a layout call:
0 CoreFoundation 0x00007fff92ea364c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8acd16de objc_exception_throw + 43
2 CoreFoundation 0x00007fff92ea34fd +[NSException raise:format:] + 205
3 UIFoundation 0x00007fff8fe4fbc1 -[NSLayoutManager(NSPrivate) _fillLayoutHoleForCharacterRange:desiredNumberOfLines:isSoft:] + 641
4 UIFoundation 0x00007fff8fe5970c _NSFastFillAllLayoutHolesForGlyphRange + 1493
5 UIFoundation 0x00007fff8fda8821 -[NSLayoutManager lineFragmentRectForGlyphAtIndex:effectiveRange:] + 39
6 AppKit 0x00007fff8ef3cb02 -[NSTextView _extendedGlyphRangeForRange:maxGlyphIndex:drawingToScreen:] + 478
7 AppKit 0x00007fff8ef3ba97 -[NSTextView drawRect:] + 1832
8 AppKit 0x00007fff8eed9a09 -[NSView(NSInternal) _recursive:displayRectIgnoringOpacity:inGraphicsContext:CGContext:topView:shouldChangeFontReferenceColor:] + 1186
9 AppKit 0x00007fff8eed9458 __46-[NSView(NSLayerKitGlue) drawLayer:inContext:]_block_invoke + 218
10 AppKit 0x00007fff8eed91f1 -[NSView(NSLayerKitGlue) _drawViewBackingLayer:inContext:drawingHandler:] + 2407
11 AppKit 0x00007fff8eed8873 -[NSView(NSLayerKitGlue) drawLayer:inContext:] + 108
12 AppKit 0x00007fff8efaafd2 -[NSTextView drawLayer:inContext:] + 179
13 AppKit 0x00007fff8ef22f76 -[_NSBackingLayerContents drawLayer:inContext:] + 145
14 QuartzCore 0x00007fff9337c177 -[CALayer drawInContext:] + 119
15 AppKit 0x00007fff8ef22aae -[_NSTiledLayer drawTile:inContext:] + 625
16 AppKit 0x00007fff8ef227df -[_NSTiledLayerContents drawLayer:inContext:] + 169
17 QuartzCore 0x00007fff9337c177 -[CALayer drawInContext:] + 119
18 AppKit 0x00007fff8f6efd64 -[NSTileLayer drawInContext:] + 169
19 QuartzCore 0x00007fff9337b153 CABackingStoreUpdate_ + 3306
20 QuartzCore 0x00007fff9337a463 ___ZN2CA5Layer8display_Ev_block_invoke + 59
21 QuartzCore 0x00007fff9337a41f x_blame_allocations + 81
22 QuartzCore 0x00007fff93379f1c _ZN2CA5Layer8display_Ev + 1546
23 AppKit 0x00007fff8ef226ed -[NSTileLayer display] + 119
24 AppKit 0x00007fff8ef1ec34 -[_NSTiledLayerContents update:] + 5688
25 AppKit 0x00007fff8ef1d337 -[_NSTiledLayer display] + 375
26 QuartzCore 0x00007fff93379641 _ZN2CA5Layer17display_if_neededEPNS_11TransactionE + 603
27 QuartzCore 0x00007fff93378d7d _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 35
28 QuartzCore 0x00007fff9337850e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
29 QuartzCore 0x00007fff93378164 _ZN2CA11Transaction6commitEv + 390
30 QuartzCore 0x00007fff93388f55 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 71
31 CoreFoundation 0x00007fff92dc0d87 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
32 CoreFoundation 0x00007fff92dc0ce0 __CFRunLoopDoObservers + 368
33 CoreFoundation 0x00007fff92db2f1a __CFRunLoopRun + 1178
34 CoreFoundation 0x00007fff92db2838 CFRunLoopRunSpecific + 296
35 UIFoundation 0x00007fff8fdfe744 -[NSHTMLReader _loadUsingWebKit] + 2097
36 UIFoundation 0x00007fff8fdffb55 -[NSHTMLReader attributedString] + 22
37 UIFoundation 0x00007fff8fe12cca _NSReadAttributedStringFromURLOrData + 10543
38 UIFoundation 0x00007fff8fe10306 -[NSAttributedString(NSAttributedStringUIFoundationAdditions) initWithData:options:documentAttributes:error:] + 115
What is wrong, given that everything is between beginEditing and endEditing?
From the stack trace (which is not complete), it looks like a run loop source is firing at an inopportune moment.
NSAttributedString uses WebKit to parse HTML. WebKit sometimes runs the run loop. For the general case, it may need to fetch resources from the network to render properly. Since that takes time, it runs the run loop to wait for the result and process other things at the same time.
One of the other run loop sources seems to be a Core Animation source to do the next step in some animation (scrolling the text view, presumably).
You didn't show all of the code between beginEditing and endEditing. I suspect you have constructed an NSAttributedString from HTML or data fetched from a URL in between those two places. That allows the Core Animation run loop source to fire. That asks the text view to draw, which asks its layout manager to lay out the text. This is occurring after beginEditing but before endEditing, which is the cause for the exception.
So, try reordering your code to construct all NSAttributedStrings before beginEditing.
And file a bug with Apple. In my opinion, when NSAttributeString uses WebKit to render HTML, it needs to make WebKit use a private run loop mode so no other sources can fire. They may prefer a different solution, but the bug is real.
As far as I can tell, there's no fix for this. An alternative that works is storing the matches as attributed strings in an array, and using an NSTableView to show the matches by setting the textField.attributedStringValue (calling reloadData every time you add a new match); something like this (where matchContent is an NSMutableArray):
-(void)addMatch:(NSDictionary*)options{
...
[matchContent addObject:text];
[resultTableView reloadData];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return matchContent.count;
}
- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
NSTableCellView *result = [tableView makeViewWithIdentifier:#"MyView" owner:self];
result.textField.attributedStringValue = [matchContent objectAtIndex:row];
return result;
}
If the result is multi-line, you may also need to check the autoresizing mask of the cell/text field, and return the row height for the table view using the attributed string's boundingRectWithSize method.

Problems when deselecting checkboxes inside bound NSTableview's columns

I am using this project, created by aneesh171 that shows the creation of checkboxes inside NSTableView and how to bind them. I am new to OSX development and trying to understand how it works.
The project is basically checkboxes inside a NSTableView's column that is bound to an array controller.
For some reason, when I deselect one of those checkboxes, the following messages appear on the console window:
2014-04-03 04:22:55.579 MyApp[5735:303] Error setting value for key path objectValue.selected of object <NSAutounbinder: 0x600000258120 - a nonretaining proxy for <NSTableCellView: 0x60000019f890>> (from bound object <NSButton: 0x60000015efb0>): [<__NSDictionaryI 0x61000006f540> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key selected.
2014-04-03 04:22:55.581 MyApp[5735:303] (
0 CoreFoundation 0x00007fff87b3a25c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff8a3f6e75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff87b3a038 +[NSException raise:format:arguments:] + 104
3 AppKit 0x00007fff927936c5 -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 837
4 AppKit 0x00007fff92793327 -[NSBinder setValue:forBinding:error:] + 245
5 AppKit 0x00007fff92c8b4ee -[NSValueBinder _applyObjectValue:forBinding:canRecoverFromErrors:handleErrors:typeOfAlert:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:] + 194
6 AppKit 0x00007fff92c8b871 -[NSValueBinder applyDisplayedValueHandleErrors:typeOfAlert:canRecoverFromErrors:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:error:] + 621
7 AppKit 0x00007fff927c5107 -[NSValueBinder performAction:] + 288
8 AppKit 0x00007fff927c4fc5 -[_NSBindingAdaptor _objectDidTriggerAction:bindingAdaptor:] + 133
9 AppKit 0x00007fff927531a0 -[NSControl sendAction:to:] + 56
10 AppKit 0x00007fff9279fced -[NSCell _sendActionFrom:] + 128
11 AppKit 0x00007fff927b96c5 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2316
12 AppKit 0x00007fff927b8a97 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 487
13 AppKit 0x00007fff927b81ad -[NSControl mouseDown:] + 706
14 AppKit 0x00007fff92739b48 -[NSWindow sendEvent:] + 11296
15 AppKit 0x00007fff926d86e4 -[NSApplication sendEvent:] + 2021
16 AppKit 0x00007fff92528b89 -[NSApplication run] + 646
17 AppKit 0x00007fff92513913 NSApplicationMain + 940
18 MyApp 0x0000000100049132 main + 34
19 libdyld.dylib 0x00007fff85ffe5fd start + 1
When the checkbox is selected this message does not show on the console.
Can you guys tell me what is wrong?
I updated the git version of the project.
Whenever you bind a control through value binding, then it calls its getter method to load the values. whereas when you tries to modify these values, it will try to call the setter method of the property. In the project the dictionaries were hardcoded therefore there were no setter method and that is the reason why you got the "Error setting value for key path objectValue.selected".
Check the new version where the FruitModel has been created which resolves the setter issue.
Let me know if you face any problems.

Detecting tab view change Xcode OSX AppleScriptObjC

I am building an application in AppleScriptObjC and I have a beginner question - how can I handle clicking on tab buttons in my app? I'm trying to make it have different sizes for each tab. I can make the window resize, but not when you click on a tab. Anyway, I've connected the tab view to the delegate
and such, and added a didSelectTabView function as follows:
on didSelectTabViewItem_(tabItem)
display alert "Testing"
end didSelectTabViewItem_
...and I get the following error:
2013-05-30 18:50:10.970 MacUtil[16354:303] Error setting value for key path self of object <AppDelegate #0x1005d3040: OSAID(4)> (from bound object <NSTabView: 0x101c05490>): [<AppDelegate 0x1005d3040> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key self.
2013-05-30 18:50:10.972 MacUtil[16354:303] (
0 CoreFoundation 0x00007fff911210a6 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff9522e3f0 objc_exception_throw + 43
2 CoreFoundation 0x00007fff91120ee8 +[NSException raise:format:arguments:] + 104
3 AppKit 0x00007fff92e3414c -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 902
4 AppKit 0x00007fff92e33d6d -[NSBinder setValue:forBinding:error:] + 248
5 AppKit 0x00007fff93493625 -[NSViewStateBinder _setValue:forBinding:errorFallbackMessage:] + 63
6 AppKit 0x00007fff933a5198 -[NSTabViewBinder tabView:didSelectTabViewItem:] + 330
7 AppKit 0x00007fff934b9c75 -[_NSBindingAdaptor tabView:didSelectTabViewItem:] + 136
8 AppKit 0x00007fff92fe9029 -[NSTabView selectTabViewItem:] + 1172
9 AppKit 0x00007fff9303ea8c -[NSTabView mouseDown:] + 156
10 AppKit 0x00007fff92fad60e -[NSWindow sendEvent:] + 6853
11 AppKit 0x00007fff92fa9744 -[NSApplication sendEvent:] + 5761
12 AppKit 0x00007fff92ebf2fa -[NSApplication run] + 636
13 AppKit 0x00007fff92e63cb6 NSApplicationMain + 869
14 MacUtil 0x0000000100000f0a main + 74
15 libdyld.dylib 0x00007fff93a297e1 start + 0
16 ??? 0x0000000000000003 0x0 + 3
)
Any help would be appreciated!
Solved! I just had to uncheck "Raises for Non Applicable Keys" in the place where you bind it to the app delegate. It was doing that because I hadn't implemented all of the methods for tab view event handling.

Reusing NSArrayController in multiple places

I have a simple NSArrayController hooked up to one of my coreData models. I can easily show all the items in a NSTableView without problem, however, if I try to bind a NSTableColumn containing a NSPopUpButtonCell to the arrangedObjects on the same controller, I get a nasty exception thrown at me. (If I bind to a NSPopupButton that is outside the table, however, everything seems to work correctly)
Catchpoint 2 (throw)2011-12-18 16:00:07.251 MyApp[6050:707] -[MyCoreDataModel count]: unrecognized selector sent to instance 0x10045aea0
Catchpoint 2 (exception thrown).2011-12-18 16:01:32.901 MyApp[6050:707] -[MyCoreDataModel count]: unrecognized selector sent to instance 0x10045aea0
2011-12-18 16:01:32.907 MyApp[6050:707] (
0 CoreFoundation 0x00007fff9191e286 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff93bd6d5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff919aa4ce -[NSObject doesNotRecognizeSelector:] + 190
3 CoreFoundation 0x00007fff9190b133 ___forwarding___ + 371
4 CoreFoundation 0x00007fff9190af48 _CF_forwarding_prep_0 + 232
5 AppKit 0x00007fff8b5bbad3 -[_NSSelectionBinderPlugin populateObject:withContent:valueKey:objectKey:insertsNullPlaceholder:] + 235
6 AppKit 0x00007fff8b45242e -[NSSelectionBinder _adjustObject:mode:observedController:observedKeyPath:context:editableState:adjustState:] + 678
7 AppKit 0x00007fff8b56f11a -[NSValueBinder updateTableColumnDataCell:forDisplayAtIndex:] + 145
8 AppKit 0x00007fff8b5af502 -[_NSBindingAdaptor tableColumn:willDisplayCell:row:] + 112
9 AppKit 0x00007fff8b0a00b1 -[NSTableView _tryCellBasedMouseDown:atRow:column:withView:] + 498
10 AppKit 0x00007fff8b062a4c -[NSTableView mouseDown:] + 1072
11 AppKit 0x00007fff8afc90e0 -[NSWindow sendEvent:] + 6306
12 AppKit 0x00007fff8af6168f -[NSApplication sendEvent:] + 5593
13 AppKit 0x00007fff8aef7682 -[NSApplication run] + 555
14 AppKit 0x00007fff8b17680c NSApplicationMain + 867
15 InstaLibrary 0x0000000100001732 main + 34
16 InstaLibrary 0x0000000100001704 start + 52
Why is this the case? How come you can't reuse the array controller in multiple places?
How come you can't reuse the array controller in multiple places?
That's not what the error message says. What the error message says is that you tried to bind an array property to a property whose value is not an array:
2011-12-18 16:01:32.901 MyApp[6050:707] -[MyCoreDataModel count]: unrecognized selector sent to instance 0x10045aea0
Meaning “I tried to treat this as an array (send it count), but it wasn't an array (and so didn't respond to count), and that's a problem”.
You've already identified the problem binding, so now you simply need to fix it. For more specific advice, you'll need to edit your question to include at least one screenshot of the binding in question, showing what object is it on, which binding is it, what object did you bind to, what controller key did you set, and what model key path did you set.

Override NSWindow close button

I'm working on a application for OS X where I use a custom window that draws an image as the background, including the title bar. I've been modifying this code to draw the window, and then calling [NSWindow standardWindowButton:forStyleMask:] to get the standard close, minimize, and maximize buttons.
The problem is my application uses NSPopovers, and when I close or minimize the application while a popover is open, it will close the popover or show an animation of the popover minimizing instead of closing the application. Is there a way to override the default close/minimize behavior in an NSWindow so I can dismiss any open popovers first?
Thanks, and sorry if this is an obvious question — this is my first time working with the OS X SDK so I don't have a lot of experience.
EDIT: A few hours after I posted this I thought I had an obvious solution – use the NSWindowDelegate methods "windowWillClose:" and "windowWillMiniaturize:" and dismiss the popovers there. However, it seems that since the close/minimize buttons are closing the popover, that if a popover is open, these delegate methods won't be called. This takes me back to step 1, but hopefully knowing the behavior will help someone figure out the problem.
There's also another problem in with the NSPopovers and I don't know if it's connected or not, so I thought I would add it here just in case there was a common cause. Sometimes, when I attempt to dismiss a popover, I'll get this error (for context, I'm pressing an NSButton that calls a function that checks for the existence of the popover, and if it exists, closes it):
2011-08-30 11:24:08.949 Playground[11194:707] *** Assertion failure in +[NSView _findFirstKeyViewInDirection:forKeyLoopGroupingView:], /SourceCache/AppKit/AppKit-1138/AppKit.subproj/NSView.m:11026
2011-08-30 11:24:08.950 Playground[11194:707] this method is supposed to only be invoked on top level items
2011-08-30 11:24:08.958 Playground[11194:707] (
0 CoreFoundation 0x00007fff873d4986 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff87ac6d5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff873d47ba +[NSException raise:format:arguments:] + 106
3 Foundation 0x00007fff8950314f -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 169
4 AppKit 0x00007fff88211064 +[NSView _findFirstKeyViewInDirection:forKeyLoopGroupingView:] + 137
5 AppKit 0x00007fff87d1f546 _replacementKeyViewAlongKeyViewPath + 565
6 AppKit 0x00007fff87d1f2ff -[NSView nextValidKeyView] + 179
7 AppKit 0x00007fff87d1f199 -[NSWindow _selectFirstKeyView] + 714
8 AppKit 0x00007fff882361cf _NSWindowRecursiveFindFirstResponder + 164
9 AppKit 0x00007fff882395c8 _NSWindowExchange + 79
10 AppKit 0x00007fff883a7e3a -[_NSWindowTransformAnimation startAnimation] + 426
11 AppKit 0x00007fff87c98bb2 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 592
12 AppKit 0x00007fff87c9890f -[NSWindow orderWindow:relativeTo:] + 154
13 AppKit 0x00007fff883dfaf0 _NSPopoverCloseAndAnimate + 948
14 Playground 0x00000001000078a4 -[MainWindowController dismissPopover:] + 100
15 Playgorund 0x0000000100007012 -[MainWindowController requestWasClicked:] + 98
16 CoreFoundation 0x00007fff873c411d -[NSObject performSelector:withObject:] + 61
17 AppKit 0x00007fff87ca2852 -[NSApplication sendAction:to:from:] + 139
18 AppKit 0x00007fff87ca2784 -[NSControl sendAction:to:] + 88
19 AppKit 0x00007fff87ca26af -[NSCell _sendActionFrom:] + 137
20 AppKit 0x00007fff87ca1b7a -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2014
21 AppKit 0x00007fff87d2157c -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 489
22 AppKit 0x00007fff87ca0786 -[NSControl mouseDown:] + 786
23 AppKit 0x00007fff87c6b66e -[NSWindow sendEvent:] + 6280
24 AppKit 0x00007fff87c03f19 -[NSApplication sendEvent:] + 5665
25 AppKit 0x00007fff87b9a42b -[NSApplication run] + 548
26 AppKit 0x00007fff87e1852a NSApplicationMain + 867
27 Playground 0x0000000100001c52 main + 34
28 Playground 0x0000000100001c24 start + 52
29 ??? 0x0000000000000001 0x0 + 1
)
The solution turned out to be fairly simple.
When I created the button on the NSWindow, I changed the action and target of the button:
[closeButton setTarget:self.delegate]; // alternatively you can make it self.windowController
[closeButton setAction:#selector(closeThisWindow:)];
And then in the NSWindowController subclass, I implemented the method:
-(void)closeThisWindow {
[self close]; // for the minimize button you'll call [self.window miniaturize]
}
For some reason, the NSPopovers always reappear when the window is reopened or unminimized; since I actually want this behavior in my application, it's not a problem, but it's something to keep in mind if you use this solution. If you don't have any child windows, then you can just iterate through self.window.childWindows because NSPopovers are considered child windows. If you have other child windows you want to handle separately, you could add an array to the NSWindow subclass that monitors all of your popovers and just iterate through that.

Resources