NSString drawInRect:withAttributes: causes 'unrecognized selector sent to instance ...' - objective-c

I got something really strange: a method causes unrecognized selector sent to instance, but doesn't NSLog() anything at all.
I made a custom NSControl subclass, where I try to draw my custom cells like this:
- (void)drawRect:(NSRect)dirtyRect {
NSLog(#"DrawRect entered!");
[[NSColor grayColor] set];
[NSBezierPath fillRect:[self bounds]];
unsigned int i, count = [cells count];
NSRect cellRect = NSMakeRect(0, 0, ([self bounds]).size.width, cellHeight);
for (i = 0; i < count; i++) {
NSLog(#"Drawing cell %d at: %#", i, NSStringFromRect(cellRect));
MKMenuCell *cell = [cells objectAtIndex:i];
[cell drawWithFrame:cellRect inView:self];
cellRect.origin.y += cellHeight;
}
}
And -[MKMenuCell drawWithFrame:inView:]:
- (void)drawWithFrame:(NSRect)bounds inView:(NSView *)controlView {
NSLog(#"-drawWithFrame:inView:");
NSMutableDictionary *strAttribs = [[NSMutableDictionary alloc] init];
[strAttribs setObject:[NSColor blackColor] forKey:NSFontAttributeName];
[name drawInRect:bounds withAttributes:strAttribs]; // "unrecognized selector sent ..." is caused by this method call.
}
The output:
2013-03-11 18:46:54.823 MacOverflow[738:a0f] DrawRect entered!
2013-03-11 18:46:54.826 MacOverflow[738:a0f] Drawing cell 0 at: {{0, 0}, {176, 30}}
2013-03-11 18:46:54.826 MacOverflow[738:a0f] -drawWithFrame:inView:
2013-03-11 18:46:54.827 MacOverflow[738:a0f] Drawing cell 1 at: {{0, 30}, {176, 30}}
2013-03-11 18:46:54.828 MacOverflow[738:a0f] -drawWithFrame:inView:
2013-03-11 18:46:54.828 MacOverflow[738:a0f] -[NSCachedWhiteColor screenFontWithRenderingMode:]: unrecognized selector sent to instance 0x100512920
2013-03-11 18:46:54.829 MacOverflow[738:a0f] An uncaught exception was raised
2013-03-11 18:46:54.831 MacOverflow[738:a0f] -[NSCachedWhiteColor screenFontWithRenderingMode:]: unrecognized selector sent to instance 0x100512920
2013-03-11 18:46:54.834 MacOverflow[738:a0f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCachedWhiteColor screenFontWithRenderingMode:]: unrecognized selector sent to instance 0x100512920'
*** Call stack at first throw:
(
0 CoreFoundation 0x00007fff88c26784 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x00007fff858ddf03 objc_exception_throw + 45
2 CoreFoundation 0x00007fff88c80110 +[NSObject(NSObject) doesNotRecognizeSelector:] + 0
3 CoreFoundation 0x00007fff88bf88ef ___forwarding___ + 751
4 CoreFoundation 0x00007fff88bf4a38 _CF_forwarding_prep_0 + 232
5 AppKit 0x00007fff89afcfae +[NSStringDrawingTextStorage _fastDrawString:attributes:length:inRect:graphicsContext:baselineRendering:usesFontLeading:usesScreenFont:typesetterBehavior:paragraphStyle:lineBreakMode:boundingRect:padding:scrollable:] + 402
6 AppKit 0x00007fff896db539 _NSStringDrawingCore + 1588
7 MacOverflow 0x00000001000159b7 -[MKMenuCell drawWithFrame:inView:] + 229
8 MacOverflow 0x0000000100015f1e -[MKMenuControl drawRect:] + 595
9 AppKit 0x00007fff896d6cc5 -[NSView _drawRect:clip:] + 3390
10 AppKit 0x00007fff896d5938 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 1325
11 AppKit 0x00007fff896d5ca2 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2199
12 AppKit 0x00007fff896d5ca2 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2199
13 AppKit 0x00007fff896d5ca2 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2199
14 AppKit 0x00007fff896d400a -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 767
15 AppKit 0x00007fff896d3b2c -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 254
16 AppKit 0x00007fff896d03de -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 2683
17 AppKit 0x00007fff89649c0e -[NSView displayIfNeeded] + 969
18 AppKit 0x00007fff89611c3b -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 1050
19 AppKit 0x00007fff896117d2 -[NSWindow orderWindow:relativeTo:] + 94
20 AppKit 0x00007fff895dd974 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1726
21 AppKiProgram received signal: “SIGABRT”.
t 0x00007fff895dba91 loadNib + 226
22 AppKit 0x00007fff895dafa1 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 248
23 AppKit 0x00007fff895dadd9 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 326
24 AppKit 0x00007fff895d835b NSApplicationMain + 279
25 MacOverflow 0x0000000100000ef9 main + 33
26 MacOverflow 0x0000000100000ed0 start + 52
27 ??? 0x0000000000000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
As you can see MKMenuCell's drawWithFrame:inView: is called. but the output from its NSLog() statement isn't displayed. What is happening here? How to solve it?
EDIT: I now realize, looking at the GDB output, the first time nothing goes wrong. This makes it even stranger.

The bad selector being sent, screenFontWithRenderingMode, is a method on NSFont. I'm betting that you shouldn't be setting a color for the value of the key NSFontAttributeName. You should probably give it a font.

Related

The contentViewController ((null)) or contentViewController.view is nil

I get the following error and stacktrace however the view is not nil (as shown by the logging down right before it)
Stacktrace
2014-02-05 08:29:47.338 MenuTimer[74522:303] An uncaught exception was raised
2014-02-05 08:29:47.338 MenuTimer[74522:303] The contentViewController ((null)) or contentViewController.view is nil.
2014-02-05 08:29:47.340 MenuTimer[74522:303] (
0 CoreFoundation 0x00007fff8e39341c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff87b1ee75 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8e3932cc +[NSException raise:format:] + 204
3 AppKit 0x00007fff8157e3da -[NSPopover showRelativeToRect:ofView:preferredEdge:] + 228
4 MenuTimer 0x0000000100002a72 -[MenuTimer onSetTime:] + 818
5 AppKit 0x00007fff814f83d0 -[NSApplication sendAction:to:from:] + 327
6 AppKit 0x00007fff81513348 -[NSMenuItem _corePerformAction] + 394
7 AppKit 0x00007fff81513084 -[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 117
8 AppKit 0x00007fff815624dd -[NSMenu _internalPerformActionForItemAtIndex:] + 35
9 AppKit 0x00007fff81562359 -[NSCarbonMenuImpl _carbonCommandProcessEvent:handlerCallRef:] + 104
10 AppKit 0x00007fff81509176 NSSLMMenuEventHandler + 716
11 HIToolbox 0x00007fff8acff6d4 _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 892
12 HIToolbox 0x00007fff8acfec87 _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 385
13 HIToolbox 0x00007fff8ad12d90 SendEventToEventTarget + 40
14 HIToolbox 0x00007fff8ad48a30 _ZL18SendHICommandEventjPK9HICommandjjhPKvP20OpaqueEventTargetRefS5_PP14OpaqueEventRef + 420
15 HIToolbox 0x00007fff8ad7b618 SendMenuCommandWithContextAndModifiers + 59
16 HIToolbox 0x00007fff8ad7b5c4 SendMenuItemSelectedEvent + 178
17 HIToolbox 0x00007fff8ad7b4a5 _ZL19FinishMenuSelectionP13SelectionDataP10MenuResultS2_ + 94
18 HIToolbox 0x00007fff8ad5956e _ZL19PopUpMenuSelectCoreP8MenuData5PointdS1_tjPK4RecttjS4_S4_PK10__CFStringPP13OpaqueMenuRefPt + 1726
19 HIToolbox 0x00007fff8ad586c6 _HandlePopUpMenuSelection7 + 596
20 AppKit 0x00007fff81561221 _NSSLMPopUpCarbonMenu3 + 4153
21 AppKit 0x00007fff815601d6 _NSPopUpCarbonMenu3 + 39
22 AppKit 0x00007fff8155fe96 -[NSCarbonMenuImpl popUpMenu:atLocation:width:forView:withSelectedItem:withFont:withFlags:withOptions:] + 350
23 AppKit 0x00007fff81950959 +[NSStatusBarButtonCell popupStatusBarMenu:inRect:ofView:withEvent:] + 699
24 AppKit 0x00007fff81951ade -[NSStatusItem popUpStatusItemMenu:] + 173
25 MenuTimer 0x0000000100001779 -[StatusBarView mouseDown:] + 633
26 AppKit 0x00007fff814ded08 -[NSWindow sendEvent:] + 11296
27 AppKit 0x00007fff815da11b -[NSStatusBarWindow sendEvent:] + 247
28 AppKit 0x00007fff8147d744 -[NSApplication sendEvent:] + 2021
29 AppKit 0x00007fff812cda29 -[NSApplication run] + 646
30 MenuTimer 0x0000000100002500 -[MenuTimer init] + 2112
31 MenuTimer 0x00000001000031b5 main + 101
32 libdyld.dylib 0x00007fff87fcc5fd start + 1
)
However the following code and output indicates differently. Is it because I don't have an explicit controller?
Code
// create set time window
NSLog(#"Set Time...");
NSLog(#"View %#", self.statusTime.view);
NSLog(#"Frame %#", self.statusTime.view.frame);
NSPopover *popover = [[NSPopover alloc] init];
NSLog(#"Showing popover...");
[popover showRelativeToRect:[self.statusTime.view frame]
ofView:self.statusTime.view
preferredEdge:NSMinYEdge];
Output
2014-02-05 08:29:47.237 MenuTimer[74522:303] Set Time...
2014-02-05 08:29:47.237 MenuTimer[74522:303] View <StatusBarView: 0x6080001b05a0>
2014-02-05 08:29:47.238 MenuTimer[74522:303] Frame <StatusBarView: 0x6080001b05a0>
2014-02-05 08:29:47.238 MenuTimer[74522:303] Showing popover...
You need to set the contentViewController (what the popover is actually showing) before showing it.
i.e.
NSViewController *viewController; // some view controller created programmatically or from a nib
NSPopover *popover = [[NSPopover alloc] init];
popover.contentViewController = viewController; // Missing this.
NSLog(#"Showing popover...");
[popover showRelativeToRect:[self.statusTime.view frame]
ofView:self.statusTime.view
preferredEdge:NSMinYEdge];
The ofView: parameter is just where the popover is being shown from.

Getting error after execute NSMutableArray

Here is the code. I tried to create a object which includes the name, size and image(get from the resource) and then I add that object into NSMutableArray in order to show those object in NSTableView. However, after I run the code, I did get the correct counts of object in NSMutableArray and correct information in each object(name,size,image), but it still gives me error. Could you guys help me. I am a new Mac developer. Thanks !!
Here is the code:
#implementation AppDelegate{
NSMutableArray* _tableContents;
}
-(void)awakeFromNib{
NSString* imagePath = #"USB.png";
NSString* mountPath = #"/Volumes";
_tableContents = [[NSMutableArray alloc]init];
for(mountPath in [[NSWorkspace sharedWorkspace]mountedLocalVolumePaths])
{
if(0==[mountPath rangeOfString:#"/Volumes/"].location)
{
NSString* USBpath = [[[NSWorkspace sharedWorkspace]mountedLocalVolumePaths]objectAtIndex:count];
//get the name of USB drive
NSString* nameOfUSB = [USBpath substringFromIndex:9];
//get the size of USB drive
NSNumber *volumeSize;
NSURL *mountPathPicked = [NSURL fileURLWithPath:mountPath];
if([mountPathPicked getResourceValue:&volumeSize forKey:NSURLVolumeTotalCapacityKey error:nil])
{
NSDictionary *obj = #{#"name":nameOfUSB,
#"image":[NSImage imageNamed:imagePath],
#"size":volumeSize
};
//after I call the following line, it will give me error !!
[_tableContents addObject:obj];
}
}
count ++;
}
}
//I also use the following two methods in order to show the name, and image in NSTableView
-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
return [_tableCountents count];
}
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
NSDictionary *flag = _tableContents[row];
NSString *identifier = [tableColumn identifier];//call different col we need identifier
if([identifier isEqualToString:#"MainCell"])
{
NSTableCellView *cellView = [tableView makeViewWithIdentifier:#"MainCell" owner:self];//give back specific cell named mainCell
[cellView.textField setStringValue:flag[#"name"]];
[cellView.imageView setImage:flag[#"image"]];
return cellView;
}
return nil;
}
There is no connection problems in GUI. And here is the error message:
2013-04-25 01:16:41.321 NAMEOFPROJECT[8243:303] An uncaught exception was raised
2013-04-25 01:16:41.322 NAMEOFPROJECT[8243:303] *** -[__NSArrayI objectAtIndex:]: index 7 beyond bounds [0 .. 3]
2013-04-25 01:16:41.329 NAMEOFPROJECT[8243:303] (
0 CoreFoundation 0x00007fff9147cb06 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff900c03f0 objc_exception_throw + 43
2 CoreFoundation 0x00007fff9142fb53 -[__NSArrayI objectAtIndex:] + 163
3 CDTOANYDRIVE 0x00000001000011d6 -[AppDelegate DetectingUSBDrives] + 710
4 CDTOANYDRIVE 0x0000000100000efb -[AppDelegate awakeFromNib] + 43
5 AppKit 0x00007fff899631a8 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1234
6 AppKit 0x00007fff89b79976 -[NSNib _instantiateNibWithExternalNameTable:] + 610
7 AppKit 0x00007fff89b7a41a -[NSNib instantiateNibWithExternalNameTable:] + 17
8 AppKit 0x00007fff89b262b4 -[NSTableRowData _unarchiveViewWithIdentifier:owner:] + 520
9 CDTOANYDRIVE 0x000000010000174b -[AppDelegate tableView:viewForTableColumn:row:] + 219
10 AppKit 0x00007fff89b279a2 -[NSTableRowData _addViewToRowView:atColumn:row:] + 324
11 AppKit 0x00007fff89b2766f -[NSTableRowData _addViewsToRowView:atRow:] + 151
12 AppKit 0x00007fff89b25c05 -[NSTableRowData _addRowViewForVisibleRow:withPriorView:] + 415
13 AppKit 0x00007fff89b2598a -[NSTableRowData _addRowViewForVisibleRow:withPriorRowIndex:inDictionary:withRowAnimation:] + 272
14 AppKit 0x00007fff89b24c59 -[NSTableRowData _unsafeUpdateVisibleRowEntries] + 740
15 AppKit 0x00007fff89b247f1 -[NSTableRowData updateVisibleRowViews] + 119
16 AppKit 0x00007fff89afc5d7 -[NSTableView layout] + 165
17 AppKit 0x00007fff89aafe95 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 112
18 CoreFoundation 0x00007fff914754a6 __NSArrayEnumerate + 582
19 AppKit 0x00007fff89aafff6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
20 CoreFoundation 0x00007fff914754a6 __NSArrayEnumerate + 582
21 AppKit 0x00007fff89aafff6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
22 CoreFoundation 0x00007fff914754a6 __NSArrayEnumerate + 582
23 AppKit 0x00007fff89aafff6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
24 CoreFoundation 0x00007fff914754a6 __NSArrayEnumerate + 582
25 AppKit 0x00007fff89aafff6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
26 AppKit 0x00007fff89aafd2e -[NSView layoutSubtreeIfNeeded] + 615
27 AppKit 0x00007fff89aab4dc -[NSWindow(NSConstraintBasedLayout) layoutIfNeeded] + 201
28 AppKit 0x00007fff899d96a8 -[NSView _layoutAtWindowLevelIfNeeded] + 99
29 AppKit 0x00007fff899d8fe6 -[NSView _sendViewWillDrawInRect:clipRootView:] + 87
30 AppKit 0x00007fff899a59b1 -[NSView displayIfNeeded] + 1044
31 AppKit 0x00007fff89a62a48 -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 1377
32 AppKit 0x00007fff89a62068 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 940
33 AppKit 0x00007fff89a61c4f -[NSWindow orderWindow:relativeTo:] + 159
34 AppKit 0x00007fff89963266 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1424
35 AppKit 0x00007fff8994214d loadNib + 317
36 AppKit 0x00007fff89941679 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 219
37 AppKit 0x00007fff899414ae -[NSBundle(NSNibLoading) loadNibNamed:owner:topLevelObjects:] + 200
38 AppKit 0x00007fff8994128e +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 360
39 AppKit 0x00007fff8993da2f NSApplicationMain + 398
40 CDTOANYDRIVE 0x0000000100000e82 main + 34
41 libdyld.dylib 0x00007fff9385a7e1 start + 0
42 ??? 0x0000000000000003 0x0 + 3
)
And the above error shows twice !!
I have tried your code in a mini-app and It works fine. There are few things that I might highlight:
Your exception occurs in the method DetectingUSBDrives, for which we don't have any code. I'm assuming that you have pasted the code in the awakeFromNib method.
You are using count as an index. Is this varibale initialized at zero?
The fact that the error appears twice suggests that your cell views hold a reference to your app delegate, which means that awakeFromNib is called once for each view creation. This can create many problem since you are initializing _tableOfContents there. You might want to move all that code to the init method instead.

Why does [NSTextStorage setAttributedString] crash with NSMutableAttributedString?

When I run the following Code it crashes at the last line. I don't have any idea why. This function gets called in awakeFromNib.
- (void)setMotdText:(NSString *)text
{
NSString *boldFontName = [[NSFont boldSystemFontOfSize:12] fontName];
NSMutableAttributedString *attrstr = [[NSMutableAttributedString alloc] initWithString:text];
[attrstr beginEditing];
[attrstr addAttribute:NSFontAttributeName value:boldFontName range:NSMakeRange(0, 16)];
[attrstr endEditing];
[self.motdTextView.textStorage setAttributedString:attrstr];
}
I get this crash log:
2012-06-22 11:32:22.348 MSM-Plan[20785:403] -[__NSCFConstantString _isDefaultFace]: unrecognized selector sent to instance 0x7fff79b9f380
2012-06-22 11:32:22.349 MSM-Plan[20785:403] An uncaught exception was raised
2012-06-22 11:32:22.349 MSM-Plan[20785:403] -[__NSCFConstantString _isDefaultFace]: unrecognized selector sent to instance 0x7fff79b9f380
2012-06-22 11:32:22.351 MSM-Plan[20785:403] (
0 CoreFoundation 0x00007fff8a5bef56 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8ae19d5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff8a64b1be -[NSObject doesNotRecognizeSelector:] + 190
3 CoreFoundation 0x00007fff8a5abe23 ___forwarding___ + 371
4 CoreFoundation 0x00007fff8a5abc38 _CF_forwarding_prep_0 + 232
5 AppKit 0x00007fff8e0b060c -[NSMutableAttributedString(NSMutableAttributedStringKitAdditions) fixFontAttributeInRange:] + 1249
6 AppKit 0x00007fff8e0afeb7 -[NSMutableAttributedString(NSMutableAttributedStringKitAdditions) fixAttributesInRange:] + 64
7 AppKit 0x00007fff8e19b521 -[NSTextStorage processEditing] + 107
8 AppKit 0x00007fff8e0c2564 -[NSTextStorage edited:range:changeInLength:] + 385
9 Foundation 0x00007fff8d6f4497 -[NSConcreteMutableAttributedString replaceCharactersInRange:withAttributedString:] + 328
10 AppKit 0x00007fff8e1dfd19 -[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:] + 81
11 MSM-Plan 0x000000010206af5a -[MSM_PlanAppDelegate setMotdText:] + 314
12 MSM-Plan 0x000000010206c455 -[MSM_PlanAppDelegate awakeFromNib] + 1701
13 CoreFoundation 0x00007fff8a5b5fb1 -[NSObject performSelector:] + 49
14 CoreFoundation 0x00007fff8a5b5f32 -[NSSet makeObjectsPerformSelector:] + 274
15 AppKit 0x00007fff8e0369ff -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1245
16 AppKit 0x00007fff8e02cf73 loadNib + 322
17 AppKit 0x00007fff8e02c470 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 217
18 AppKit 0x00007fff8e02c38b +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 141
19 AppKit 0x00007fff8e02c2ce +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 364
20 AppKit 0x00007fff8e29d06f NSApplicationMain + 398
21 MSM-Plan 0x000000010206adf2 main + 34
22 MSM-Plan 0x000000010206adc4 start + 52
)
2012-06-22 11:32:22.416 MSM-Plan[20785:403] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString _isDefaultFace]: unrecognized selector sent to instance 0x7fff79b9f380'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8a5bef56 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8ae19d5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff8a64b1be -[NSObject doesNotRecognizeSelector:] + 190
3 CoreFoundation 0x00007fff8a5abe23 ___forwarding___ + 371
4 CoreFoundation 0x00007fff8a5abc38 _CF_forwarding_prep_0 + 232
5 AppKit 0x00007fff8e0b060c -[NSMutableAttributedString(NSMutableAttributedStringKitAdditions) fixFontAttributeInRange:] + 1249
6 AppKit 0x00007fff8e0afeb7 -[NSMutableAttributedString(NSMutableAttributedStringKitAdditions) fixAttributesInRange:] + 64
7 AppKit 0x00007fff8e19b521 -[NSTextStorage processEditing] + 107
8 AppKit 0x00007fff8e0c2564 -[NSTextStorage edited:range:changeInLength:] + 385
9 Foundation 0x00007fff8d6f4497 -[NSConcreteMutableAttributedString replaceCharactersInRange:withAttributedString:] + 328
10 AppKit 0x00007fff8e1dfd19 -[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:] + 81
11 MSM-Plan 0x000000010206af5a -[MSM_PlanAppDelegate setMotdText:] + 314
12 MSM-Plan 0x000000010206c455 -[MSM_PlanAppDelegate awakeFromNib] + 1701
13 CoreFoundation 0x00007fff8a5b5fb1 -[NSObject performSelector:] + 49
14 CoreFoundation 0x00007fff8a5b5f32 -[NSSet makeObjectsPerformSelector:] + 274
15 AppKit 0x00007fff8e0369ff -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1245
16 AppKit 0x00007fff8e02cf73 loadNib + 322
17 AppKit 0x00007fff8e02c470 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 217
18 AppKit 0x00007fff8e02c38b +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 141
19 AppKit 0x00007fff8e02c2ce +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 364
20 AppKit 0x00007fff8e29d06f NSApplicationMain + 398
21 MSM-Plan 0x000000010206adf2 main + 34
22 MSM-Plan 0x000000010206adc4 start + 52
)
terminate called throwing an exception(lldb)
Has anybody an idea? If I call it with a NSAttributedString-Object there´s no error.
I had to change the first line to:
NSFont *boldFont = [NSFont boldSystemFontOfSize:12];
Now it works, because the value attribute requires a NSFont-Object and not a NSString with the fonts name.
This is the working Code:
- (void)setMotdText:(NSString *)text
{
NSFont *boldFont = [NSFont boldSystemFontOfSize:12];
NSMutableAttributedString *attrstr = [[NSMutableAttributedString alloc] initWithString:text];
[attrstr beginEditing];
[attrstr addAttribute:NSFontAttributeName value:boldFont range:NSMakeRange(0, 16)];
[attrstr endEditing];
[self.motdTextView.textStorage setAttributedString:attrstr];
}

Crash in drawRect - what causes it?

Some of my users are getting this crash.
As far as I can tell, it's somehow connected to the -drawRect: method of my subclassed NSTextView, but I can't see what might cause it, and stress testing has failed to shake out the bug.
Code for drawRect
- (NSRange)visibleRangeOfTextView:(NSRect) rect {
NSLayoutManager *layoutManager = [self
layoutManager];
NSTextContainer *textContainer = [self
textContainer];
NSRange glyphRange, characterRange;
// first transform to text container coordinates
NSPoint containerOrigin = [self textContainerOrigin];
rect.origin.x -= containerOrigin.x;
rect.origin.y -= containerOrigin.y;
// next, compute glyph range
glyphRange = [layoutManager glyphRangeForBoundingRect:rect inTextContainer:textContainer];
// finally, compute character range
characterRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL];
return characterRange;
}
- (NSRect)rectForCharacterRange:(NSRange)charRange
{
NSRect rect = [self
firstRectForCharacterRange:charRange];
rect.origin = [[self window]
convertScreenToBase:rect.origin];
rect = [self convertRect:rect fromView:nil];
if (!rect.size.width) rect.size.width = 6.0;
return rect;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
NSLog(#"Marking it");
NSMutableArray *arr = [[NSMutableArray alloc] init];
NSRange visible = [self visibleRangeOfTextView:dirtyRect];
NSRange last = NSMakeRange(visible.location, 0); while (true) {
NSRange error = [appController rangeOfMisspelledWordInString:self.string onlyInRange:visible startingAt:last.location + last.length];
last = error;
if (error.location == NSNotFound) {
break;
}
[arr addObject:[NSValue valueWithRange:error]];
}
NSLog(#"Spellchecked");
[[NSColor redColor] setStroke];
CGFloat dash[] = {2.0f, 2.0f} ;
// Make the text ranges and mark them
for (NSValue *val in arr) {
NSRange range = [val rangeValue];
NSRect rectInTextView = [self rectForCharacterRange:range];
NSRect toDraw = rectInTextView;
NSBezierPath* aPath = [NSBezierPath bezierPath];
[aPath setLineDash:dash count:2 phase:0];
NSPoint lineStart = toDraw.origin;
lineStart.y += toDraw.size.height;
NSPoint lineEnd = lineStart;
lineEnd.x += toDraw.size.width;
[aPath moveToPoint:lineStart];
[aPath lineToPoint:lineEnd];
[aPath stroke];
};
NSLog(#"Done");
}
Stack trace:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Application Specific Information:
objc[5751]: garbage collection is ON
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSConcreteTextStorage attribute:atIndex:longestEffectiveRange:inRange:]: Range or index out of bounds'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff91387fc6 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8d4d7d5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff91387dfa +[NSException raise:format:arguments:] + 106
3 CoreFoundation 0x00007fff91387d84 +[NSException raise:format:] + 116
4 AppKit 0x00000001005d842c -[NSConcreteTextStorage attribute:atIndex:longestEffectiveRange:inRange:] + 131
5 AppKit 0x00000001006288ec -[NSLayoutManager(NSPrivate) _drawBackgroundForGlyphRange:atPoint:parameters:] + 910
6 AppKit 0x00000001006277a2 -[NSTextView drawRect:] + 1913
7 Skrivest√∏tte 0x000000010000b56c Skrivest√∏tte + 46444
8 AppKit 0x0000000100626e66 -[NSTextView _drawRect:clip:] + 2545
9 AppKit 0x00000001004a985d -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 3020
10 AppKit 0x00000001004aa34e -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 5821
11 AppKit 0x00000001004aa34e -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 5821
12 AppKit 0x00000001004a39af -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 4755
13 AppKit 0x000000010049c395 -[NSView displayIfNeeded] + 1528
14 AppKit 0x00000001004a1592 -[NSClipView _immediateScrollToPoint:] + 6533
15 AppKit 0x000000010049fb75 -[NSClipView scrollToPoint:] + 239
16 AppKit 0x000000010058f637 -[NSScrollView scrollClipView:toPoint:] + 266
17 AppKit 0x000000010058f3da -[NSClipView _scrollTo:animateScroll:flashScrollerKnobs:] + 1497
18 AppKit 0x00000001005923b7 -[NSClipView _scrollTo:animate:] + 27
19 AppKit 0x0000000100bcd5a2 __-[NSScrollView _snapRubberBand]_block_invoke_2 + 1536
20 AppKit 0x0000000100b3fc4e ____NSPeriodicInvokerScheduled_block_invoke_2 + 53
21 libdispatch.dylib 0x00007fff907b98ba _dispatch_call_block_and_release + 18
22 libdispatch.dylib 0x00007fff907bbc07 _dispatch_after_timer_callback + 16
23 libdispatch.dylib 0x00007fff907be2b6 _dispatch_source_invoke + 635
24 libdispatch.dylib 0x00007fff907baf77 _dispatch_queue_invoke + 71
25 libdispatch.dylib 0x00007fff907bb6f7 _dispatch_main_queue_callback_4CF + 257
26 CoreFoundation 0x00007fff9131d06c __CFRunLoopRun + 1724
27 CoreFoundation 0x00007fff9131c676 CFRunLoopRunSpecific + 230
28 HIToolbox 0x00007fff93ab831f RunCurrentEventLoopInMode + 277
29 HIToolbox 0x00007fff93abf5c9 ReceiveNextEventCommon + 355
30 HIToolbox 0x00007fff93abf456 BlockUntilNextEventMatchingListInMode + 62
31 AppKit 0x000000010045ff5d _DPSNextEvent + 659
32 AppKit 0x000000010045f861 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
33 AppKit 0x000000010045c19d -[NSApplication run] + 470
34 AppKit 0x00000001006dab88 NSApplicationMain + 867
35 Skrivest√∏tte 0x0000000100001020 Skrivest√∏tte + 4128
36 ??? 0x0000000000000002 0x0 + 2
)
* Terminating app due to uncaught exception 'NSRangeException', reason: '*
[NSConcreteTextStorage attribute:atIndex:longestEffectiveRange:inRange:]: Range or index out of bounds'
It is clearly a NSRange exception, as O' y said
I think you need add assert function to check the "range"
NSRange range = [val rangeValue];
make sure range will not be NSNotFound.

Get iTunes Artwork for Current Song with ScriptingBridge

I have been trying to figure out how to get the iTunes artwork for the currently playing song with scripting bridge. I have gotten to a point where it works for some songs, but for others, I get a SIGABRT. I'm not sure what the issue could be, so any help would be greatly appreciated. Here is what I have so far:
iTunesApplication * iTunes = [SBApplication applicationWithBundleIdentifier:#"com.apple.iTunes"];
NSImage *songArtwork;
iTunesTrack *current = [iTunes currentTrack];
iTunesArtwork *artwork = (iTunesArtwork *)[[[current artworks] get] lastObject];
if(artwork != nil)
songArtwork = [artwork data];
else
songArtwork = [NSImage imageNamed:#"Image.tiff"];
NSMenuItem *artworkMenuItem = [[NSMenuItem alloc] initWithTitle:#"" action:NULL keyEquivalent:#""];
[songArtwork setSize:NSMakeSize(128, 128)];
[artworkMenuItem setImage:songArtwork];
[Menu insertItem:artworkMenuItem atIndex:0];
I for some songs it works, and displays the artwork nicely in the menu item, but for others I get a SIGABRT on the line:
[songArtwork setSize:NSMakeSize(128, 128)];
The output of the console is as follows:
2011-08-12 23:13:20.094 SongViewer[2146:707] -[NSAppleEventDescriptor setSize:]: unrecognized selector sent to instance 0x102827f70
2011-08-12 23:13:20.095 SongViewer[2146:707] An uncaught exception was raised
2011-08-12 23:13:20.096 SongViewer[2146:707] -[NSAppleEventDescriptor setSize:]: unrecognized selector sent to instance 0x102827f70
2011-08-12 23:13:20.097 SongViewer[2146:707] (
0 CoreFoundation 0x00007fff86f11986 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8b04cd5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff86f9d5ae -[NSObject doesNotRecognizeSelector:] + 190
3 CoreFoundation 0x00007fff86efe803 ___forwarding___ + 371
4 CoreFoundation 0x00007fff86efe618 _CF_forwarding_prep_0 + 232
5 SongViewer 0x0000000100002a83 -[IPMenulet awakeFromNib] + 4483
6 CoreFoundation 0x00007fff86f089e1 -[NSObject performSelector:] + 49
7 CoreFoundation 0x00007fff86f08962 -[NSSet makeObjectsPerformSelector:] + 274
8 AppKit 0x00007fff8d9d9c27 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1245
9 AppKit 0x00007fff8d9d01b9 loadNib + 322
10 AppKit 0x00007fff8d9cf6b6 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 217
11 AppKit 0x00007fff8d9cf5d1 +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 141
12 AppKit 0x00007fff8d9cf514 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 364
13 AppKit 0x00007fff8dc42355 NSApplicationMain + 398
14 SongViewer 0x0000000100001882 main + 34
15 SongViewer 0x0000000100001854 start + 52
)
2011-08-12 23:13:20.098 SongViewer[2146:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSAppleEventDescriptor setSize:]: unrecognized selector sent to instance 0x102827f70'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff86f11986 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8b04cd5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff86f9d5ae -[NSObject doesNotRecognizeSelector:] + 190
3 CoreFoundation 0x00007fff86efe803 ___forwarding___ + 371
4 CoreFoundation 0x00007fff86efe618 _CF_forwarding_prep_0 + 232
5 SongViewer 0x0000000100002a83 -[IPMenulet awakeFromNib] + 4483
6 CoreFoundation 0x00007fff86f089e1 -[NSObject performSelector:] + 49
7 CoreFoundation 0x00007fff86f08962 -[NSSet makeObjectsPerformSelector:] + 274
8 AppKit 0x00007fff8d9d9c27 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1245
9 AppKit 0x00007fff8d9d01b9 loadNib + 322
10 AppKit 0x00007fff8d9cf6b6 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 217
11 AppKit 0x00007fff8d9cf5d1 +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 141
12 AppKit 0x00007fff8d9cf514 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 364
13 AppKit 0x00007fff8dc42355 NSApplicationMain + 398
14 SongViewer 0x0000000100001882 main + 34
15 SongViewer 0x0000000100001854 start + 52
)
terminate called throwing an exception(gdb)
If anyone has any idea what could be wrong, please let me know!!
Ok so I figured it out. The solution is to use the NSData raw data provided by the API rather than the NSImage. So I used:
NSImage *songArtwork = [[NSImage alloc] initWithData:[artwork rawData]];
rather than
songArtwork = [artwork data];
I have to fetch batch of track artworks from iTunes and use ‘rawData’ too.
But this way is inefficient.
I found a better way (actually it decreases ‘fetch’ time about 2 times, it’s very significant when fetching artworks for many tracks using ‘valueForKey:’ according to «Improving the Performance of Scripting Bridge Code»).
So I decided to understand what’s wrong with iTunesArtwork ‘data’ property.
We expect to get an NSImage object (according to iTunes.h ), but real object is kind of ‘NSAppleEventDescriptor’. And it’s easy to guess, that this object contains an image for us. So we can just use ‘data’ property to get image data. And this is really faster than getting ‘rawData’ from iTunesArtwork.
But sometimes iTunes return NSImage object instead NSAppleEventDescriptor. This is an strange behavior, but it's still faster then using rawData.