Hi Tom,
Definitely write a Radar.
One thing you could try is overriding both -checkTextInRange:types:options: &
-handleTextCheckingResults:forRange:types:options:orthography:wordCount: for
your field editor.
You can have some kind of the field editor session ID.
Every time a new field editor starts, you increment the ID. Then, inside your
-checkTextInRange:, you can pass the session ID via the options dict to super.
Inside -handleTextCheckingResult:, validate the session ID inside the options
dict against the current ID. Forward the message to super only when they match.
Aki
On 2011/08/02, at 17:36, Thomas Bunch wrote:
> Hello, fellow cocoa devs.
>
> I'm running down the most common crasher we're seeing in OmniPlan-2.0 under
> Lion and running onto some grief with NSSpellChecker/NSTextView. We have a
> fairly complex outline view that is backed by many text storages and the
> field editor is asked to do a lot. When editing a row, we create a text
> storage for that row's contents, then insert a field editor into the view
> hierarchy and call -replaceTextStorage: on its layout manager with our
> freshly-minted text storage.
>
> If I enable “Correct Spelling Automatically”, create a new task and title it
> "Hello htere" [sic], spell checking is performed asynchronously on the main
> thread and the NSSpellChecker shows a correctionIndicator
>
> #0 0x00007fff8c295a5b in -[NSSpellChecker
> showCorrectionIndicatorOfType:primaryString:alternativeStrings:forStringInRect:view:completionHandler:]
> ()
> #1 0x00007fff8bf12cef in -[NSTextView
> handleTextCheckingResults:forRange:types:options:orthography:wordCount:] ()
> #2 0x00007fff8bf11565 in -[NSTextView
> _handleTextCheckingResults:sequenceNumber:forRange:types:options:orthography:wordCount:applyNow:]
> ()
> #3 0x00007fff8bf113e6 in __-[NSTextView
> checkTextInRange:types:options:]_block_invoke_2 ()
> #4 0x00007fff896a6ecc in __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ ()
> #5 0x00007fff8965efa2 in __CFRunLoopDoBlocks ()
> #6 0x00007fff89686f07 in __CFRunLoopRun ()
> …
>
> If I hit return, the default correction is selected and I infer that the
> completionHandler is enqueued on the main queue. However, our custom
> implementation of -insertNewline: will also end editing on the current row,
> create a new item with another text storage behind it, and tell the field
> editor's layout manager to replaceTextStorage: with that new row's text
> storage. After we return to the run loop, an NSPortMessage happens to be
> received by another object, and that object calls [NSApp
> nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast]
> inMode:NSEventTrackingRunLoopMode dequeue:NO], which will again fire the run
> loop. This causes the the main queue to fire its pending blocks, and thus the
> NSTextView's text checking handler's completionHandler is run and raises an
> exception:
>
> #13 0x00007fff896f1ab4 in +[NSException raise:format:] ()
> #14 0x00007fff896af87e in -[__NSCFString characterAtIndex:] ()
> #15 0x00007fff8bf17e76 in
> -[NSAttributedString(NSAttributedStringKitAdditions)
> doubleClickAtIndex:inRange:] ()
> #16 0x00007fff8bf17de7 in
> -[NSAttributedString(NSAttributedStringKitAdditions) doubleClickAtIndex:] ()
> #17 0x00007fff8bf17da4 in -[NSTextView _doubleClickAtIndex:limitedRangeOK:] ()
> #18 0x00007fff8c304d61 in __-[NSTextView
> handleTextCheckingResults:forRange:types:options:orthography:wordCount:]_block_invoke_2
> ()
> #19 0x00007fff8dbdf90a in _dispatch_call_block_and_release ()
> #20 0x00007fff8dbe177a in _dispatch_main_queue_callback_4CF ()
> #21 0x00007fff89686ddc in __CFRunLoopRun ()
> #22 0x00007fff896863e6 in CFRunLoopRunSpecific ()
> #23 0x00007fff90e5c697 in RunCurrentEventLoopInMode ()
> #24 0x00007fff90e63db9 in ReceiveNextEventCommon ()
> #25 0x00007fff90e63c46 in BlockUntilNextEventMatchingListInMode ()
> #26 0x00007fff8bd2baf5 in _DPSNextEvent ()
> #27 0x00007fff8bd2b3fc in -[NSApplication
> nextEventMatchingMask:untilDate:inMode:dequeue:] ()
> …
>
> Here, this problem occurs because the field editor's new NSTextStorage is
> shorter now (having a default task title of something like “Task 2”). The
> completion handler appears to be hanging on to the range of the
> NSTextCheckingResult it's handling, (NSRange){6, 5}. The exception we get is:
>
> ---------------------------
> Mask: 0x00000001
> Name: NSRangeException
> Reason: -[__NSCFString characterAtIndex:]: Range or index out of bounds
> Info:
>
> Because we regard an unhandled exception in a place like this as a potential
> data corruptor, we immediately crash on purpose and hope the user will send
> in a crash report with a backtrace to the scene of the crime.
>
> It just looks to me like it's unsafe to change the text storage backing the
> field editor unless you can be sure that there are no text checking
> completion blocks hanging around on the main dispatch queue. I don't believe
> there's any API or trick to get the spell checker to wrap up its text
> checking now, synchronously. Subclassing [NSTextView
> handleTextCheckingResults:forRange:types:options:orthography:wordCount:] in
> our field editor would be pretty onerous; it's a very complicated method.
>
> Your thoughts would be very welcome. I'm happy to provide more information
> of course, but I've got over half a million lines of .m files here and I'm
> trying to narrow the scope of the problem suitably. Kyle is currently across
> the hall striving to reproduce this problem in a smaller, Radar-compatible
> sample project.
>
> Thanks!
>
> -Tom_______________________________________________
>
> Cocoa-dev mailing list ([email protected])
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/aki%40apple.com
>
> This email sent to [email protected]
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]