我的一些用户正在崩溃.
据我所知,这与某些子类的NSTextView的-drawRect:方法连接起来,但是我看不到可能会导致什么,压力测试未能摆脱错误.
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"); }
堆栈跟踪:
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 )
解决方法
*由于未被捕获的异常’NSRangeException’终止应用程序,原因:’*
[NSConcreteTextStorage attribute:atIndex:longestEffectiveRange:inRange:]: Range or index out of bounds’
这显然是一个NSRange异常,正如O’y所说