I'm developing a Mac app using Swift 2 and Xcode 7.
I'm just getting started with Swift after many years focused on Ruby with a touch of JavaScript.
The Mac app that I'm creating includes a web browser view.
My ViewController.swift says:
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet var url: NSTextField!
#IBOutlet var browser: WKWebView!
#IBAction func go(sender: AnyObject) {
// browser.loadRequest(NSURLRequest(URL:NSURL(string: url.stringValue)!))
// above line broken down for debugging
let url1 = url.stringValue
print("url1 = \(url1)")
let url2 = NSURL(string: url1)!
print("url2 = \(url2)")
let url3 = NSURLRequest(URL:url2)
print("url3 = \(url3)")
print("browser is \(browser)")
browser.loadRequest(url3)
}
}
The app builds successfully. When I run it, enter http://apple.com into the URL field and click the Go button, I see:
url1 = http://apple.com
url2 = http://apple.com
url3 = <NSURLRequest: 0x600000001400> { URL: http://apple.com }
browser is <WebView: 0x608000120e60>
2016-04-06 13:39:51.664 Testivate[6516:427535] -[WebView loadRequest:]: unrecognized selector sent to instance 0x608000120e60
2016-04-06 13:39:51.664 Testivate[6516:427535] -[WebView loadRequest:]: unrecognized selector sent to instance 0x608000120e60
2016-04-06 13:39:51.667 Testivate[6516:427535] (
0 CoreFoundation 0x00007fff93f4a4f2 __exceptionPreprocess + 178
1 libobjc.A.dylib 0x00007fff8ca7a73c objc_exception_throw + 48
2 CoreFoundation 0x00007fff93fb41ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00007fff93eba571 ___forwarding___ + 1009
4 CoreFoundation 0x00007fff93eba0f8 _CF_forwarding_prep_0 + 120
5 Testivate 0x000000010000271a _TFC9Testivate14ViewController2gofPs9AnyObject_T_ + 2154
6 Testivate 0x00000001000027b6 _TToFC9Testivate14ViewController2gofPs9AnyObject_T_ + 54
7 libsystem_trace.dylib 0x00007fff96e1807a _os_activity_initiate + 75
8 AppKit 0x00007fff94567e89 -[NSApplication sendAction:to:from:] + 460
9 AppKit 0x00007fff94579fde -[NSControl sendAction:to:] + 86
10 AppKit 0x00007fff94579f08 __26-[NSCell _sendActionFrom:]_block_invoke + 131
11 libsystem_trace.dylib 0x00007fff96e1807a _os_activity_initiate + 75
12 AppKit 0x00007fff94579e65 -[NSCell _sendActionFrom:] + 144
13 libsystem_trace.dylib 0x00007fff96e1807a _os_activity_initiate + 75
14 AppKit 0x00007fff9457848a -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2693
15 AppKit 0x00007fff945c0fd0 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 744
16 AppKit 0x00007fff94576bb4 -[NSControl mouseDown:] + 669
17 AppKit 0x00007fff94acb469 -[NSWindow _handleMouseDownEvent:isDelayedEvent:] + 6322
18 AppKit 0x00007fff94acc44d -[NSWindow _reallySendEvent:isDelayedEvent:] + 212
19 AppKit 0x00007fff9450b63d -[NSWindow sendEvent:] + 517
20 AppKit 0x00007fff9448bb3c -[NSApplication sendEvent:] + 2540
21 AppKit 0x00007fff942f2ef6 -[NSApplication run] + 796
22 AppKit 0x00007fff942bc46c NSApplicationMain + 1176
23 Testivate 0x0000000100004f34 main + 84
24 libdyld.dylib 0x00007fff9099a5ad start + 1
25 ??? 0x0000000000000003 0x0 + 3
)
Initially I thought the error was saying that loadRequest was an unrecognized selector for browser, but you can see I've pulled apart the function and browser is clearly an instance of WebView, which definitely has loadRequest as a method. You can see from how I've pulled apart the method that I'm definitely providing the loadRequest method with the expected NSURLRequest object.
I'm now thinking that maybe this has something to do with being unable to find the WebView in Main.storyboard, but surely it should be able to? I've defined connections on it like this:
When you view Main.storyboard as source, it says:
<webView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ocj-mD-woP">
<rect key="frame" x="62" y="20" width="406" height="211"/>
<webPreferences key="preferences" defaultFontSize="12" defaultFixedFontSize="12">
<nil key="identifier"/>
</webPreferences>
</webView>
Any thoughts? Thanks.
You're mixing up two different kinds of web views.
In your code, you're saying that browser is a WKWebView. That's the newer kind of web view, that was first available in OS X 10.10. It has a method named -loadView: in Objective-C, or loadView() in Swift.
#IBOutlet var browser: WKWebView!
However, when you run the code, the object is actually a WebView, because that's what you put in your storyboard. That's an older kind of web view. It doesn't have a method named -loadView: so you get an error when you try to call it.
browser is <WebView: 0x608000120e60>
-[WebView loadRequest:]: unrecognized selector sent to instance 0x608000120e60
(Read the documentation you linked to again. The WebView's main frame implements -loadRequest:, but WebView does not.)
Here are two possible fixes:
Easier: Fix your code to use WebView correctly, but leave the storyboard the same.
#IBOutlet var browser: WebView!
...
browser.mainFrame.loadRequest(url3)
Harder: Keep the code using WKWebView, but remove the WebView from your storyboard.
Unfortunately it's currently impossible to put a WKWebView in a storyboard, so you will have to write some code to set it up yourself. See the linked answer for an example of how to do it.
If you want to take advantage of the new features of WKWebView, you'll have to use the second alternative.
Related
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.
I'm new to app development and I'm following Apple's tutorial to learn. I've looked through a lot of questions asked about this type of error but none of them are helping me. In the tutorial, I'm stuck on the "Add Buttons to the View" section where I'm trying to implement a string to be printed out on the console when a button is tapped/clicked on. Only I get an error when doing so.
My code for the button in Swift:
import UIKit
class StarRatingControl: UIView {
// MARK: Initialization
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
button.backgroundColor = UIColor.cyanColor()
button.addTarget(self, action: "ratingButtonTapped", forControlEvents: .TouchDown)
addSubview(button)
}
override func intrinsicContentSize() -> CGSize {
return CGSize(width: 240, height: 44)
}
// MARK: Button Action
func ratingButtonTapped(button: UIButton) {
print("Button pressed!")
}
}
The error:
2015-09-16 12:43:17.409 FoodTracker[954:13341] -[FoodTracker.StarRatingControl ratingButtonTapped]: unrecognized selector sent to instance 0x7f939b7a43b0
2015-09-16 12:43:17.443 FoodTracker[954:13341] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FoodTracker.StarRatingControl ratingButtonTapped]: unrecognized selector sent to instance 0x7f939b7a43b0'
*** First throw call stack:
(
0 CoreFoundation 0x00000001079f59b5 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001095f4deb objc_exception_throw + 48
2 CoreFoundation 0x00000001079fdfdd -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010794b9fa ___forwarding___ + 970
4 CoreFoundation 0x000000010794b5a8 _CF_forwarding_prep_0 + 120
5 UIKit 0x0000000108214522 -[UIApplication sendAction:to:from:forEvent:] + 92
6 UIKit 0x0000000108373c06 -[UIControl sendAction:to:forEvent:] + 67
7 UIKit 0x0000000108373eac -[UIControl _sendActionsForEvents:withEvent:] + 273
8 UIKit 0x0000000108372b1c -[UIControl touchesBegan:withEvent:] + 261
9 UIKit 0x000000010827bf50 -[UIWindow _sendTouchesForEvent:] + 308
10 UIKit 0x000000010827cd4d -[UIWindow sendEvent:] + 865
11 UIKit 0x00000001082312ae -[UIApplication sendEvent:] + 263
12 UIKit 0x000000010820d36c _UIApplicationHandleEventQueue + 6693
13 CoreFoundation 0x0000000107921b21 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
14 CoreFoundation 0x0000000107917a4c __CFRunLoopDoSources0 + 556
15 CoreFoundation 0x0000000107916f03 __CFRunLoopRun + 867
16 CoreFoundation 0x0000000107916918 CFRunLoopRunSpecific + 488
17 GraphicsServices 0x000000010befead2 GSEventRunModal + 161
18 UIKit 0x000000010821299e UIApplicationMain + 171
19 FoodTracker 0x00000001078118dd main + 109
20 libdyld.dylib 0x000000010a11392d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I understand that Xcode keeps old references to action/outlets that I've deleted so I tried right-clicking on the View Controller in the Interface Builder to find items with the exclamation point next to them but I couldn't find anything(only troubleshooting method I know of so far). I'm using Xcode beta 7.0. Any help is appreciated!
You're missing the ":" in the selector, try the following instead:
button.addTarget(self, action: "ratingButtonTapped:", forControlEvents: .TouchDown)
I hope this help you.
If you're using Swift 3, the line in question would have to be changed to:
button.addTarget(self, action: #selector(StarRatingControl.ratingButtonTapped), for: .touchDown)
I had the same problem,
Check the version of your Xcode.
#selector comes with Xcode 7.3
If you have an older version update and this will probably fix your errors.
Regards,
Driss
For reference, I've decided to have a look at the sample and got a similar issue.
I'm using XCode 8 + Swift 3 and these are my changes in order to get it working:
button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped), for: .touchDown)
Note: considering the file name "RatingControl.swift".
I hope it help =D
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.
I'm getting an error that I can't decipher when I try to add a tableview to a new tabbed project.
If I add the tableview to my storyboard, then build the app - it's fine. However as soon as I ctrl+drag the "delegate" and "dataSource" to that yellow circle with a square box icon to link it to my controller, the build fails. Why does this happen?
Exact repro steps:
Create a new "Tabbed View" project in Xcode.
In storyboard, I drag a "Table View" onto the top storyboard.
I "ctrl click" on the "Table View", then drag "dataSource" and "delegate" to the yellow circle + white box icon at the top of the storyboard.
I open FirstViewController.swift and I try to add UITableViewDelegate, UITableViewDataSource to the class. However neither of these show up in autocomplete as if the controller doesn't think they exist. If I command click on one, I get "symbol not found".
FirstViewController.swift
//
// FirstViewController.swift
// To Do List
//
// Created by Donald Pinkus on 12/14/14.
// Copyright (c) 2014 Don Pinkus. All rights reserved.
//
import UIKit
class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Build error
2014-12-14 00:27:04.278 To Do List[11149:566768] -[To_Do_List.FirstViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x7faafae29ba0
2014-12-14 00:27:04.285 To Do List[11149:566768] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[To_Do_List.FirstViewController tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x7faafae29ba0'
*** First throw call stack:
(
0 CoreFoundation 0x0000000105422f35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000106f66bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010542a04d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010538227c ___forwarding___ + 988
4 CoreFoundation 0x0000000105381e18 _CF_forwarding_prep_0 + 120
5 UIKit 0x0000000105f26212 -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 2353
6 UIKit 0x0000000105f2a098 -[UITableViewRowData numberOfRows] + 97
7 UIKit 0x0000000105d928fc -[UITableView noteNumberOfRowsChanged] + 133
8 UIKit 0x0000000105d9203d -[UITableView reloadData] + 1316
9 UIKit 0x0000000105d9ad86 -[UITableView layoutSubviews] + 31
10 UIKit 0x0000000105d27973 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
11 QuartzCore 0x0000000109c25de8 -[CALayer layoutSublayers] + 150
12 QuartzCore 0x0000000109c1aa0e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
13 UIKit 0x0000000105d1b847 -[UIView(Hierarchy) layoutBelowIfNeeded] + 611
14 UIKit 0x0000000105e0ff06 -[UITabBarController _layoutViewController:] + 500
15 UIKit 0x0000000105e10014 -[UITabBarController _wrapperViewForViewController:] + 252
16 UIKit 0x0000000105e16e92 -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 378
17 UIKit 0x0000000105e13069 -[UITabBarController _setSelectedViewController:] + 311
18 UIKit 0x0000000105d1f5ce +[UIView(Animation) performWithoutAnimation:] + 65
19 UIKit 0x0000000105e10106 -[UITabBarController _selectDefaultViewControllerIfNecessaryWithAppearanceTransitions:] + 221
20 UIKit 0x0000000105e10dfe -[UITabBarController viewWillAppear:] + 121
21 UIKit 0x0000000105dd7821 -[UIViewController _setViewAppearState:isAnimating:] + 487
22 UIKit 0x0000000105d1a136 -[UIView(Hierarchy) _willMoveToWindow:withAncestorView:] + 564
23 UIKit 0x0000000105d24aaa -[UIView(Internal) _addSubview:positioned:relativeTo:] + 419
24 UIKit 0x0000000105cf2e37 -[UIWindow addRootViewControllerViewIfPossible] + 456
25 UIKit 0x0000000105cf3041 -[UIWindow _setHidden:forced:] + 247
26 UIKit 0x0000000105cff72c -[UIWindow makeKeyAndVisible] + 42
27 UIKit 0x0000000105caa061 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2628
28 UIKit 0x0000000105cacd2c -[UIApplication _runWithMainScene:transitionContext:completion:] + 1350
29 UIKit 0x0000000105cabbf2 -[UIApplication workspaceDidEndTransaction:] + 179
30 FrontBoardServices 0x0000000108af32a3 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
31 CoreFoundation 0x000000010535853c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
32 CoreFoundation 0x000000010534e285 __CFRunLoopDoBlocks + 341
33 CoreFoundation 0x000000010534e045 __CFRunLoopRun + 2389
34 CoreFoundation 0x000000010534d486 CFRunLoopRunSpecific + 470
35 UIKit 0x0000000105cab669 -[UIApplication _run] + 413
36 UIKit 0x0000000105cae420 UIApplicationMain + 1282
37 To Do List 0x00000001052403ce top_level_code + 78
38 To Do List 0x000000010524040a main + 42
39 libdyld.dylib 0x0000000107740145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
You are missing the numberOfRowsInSection method which is required.
In order to be a UITableViewDataSource you are required to implement numberOfRowsInSection and cellForRowAtIndexPath
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.