Textkit comparing custom NSTextLocation against NSCountableTextLocation

137 Views Asked by At

I am trying to use a customized NSTextContentManager (with custom NSTextLocation for range and text location) with TextKit.

The primary override I have provided is via this method public override func enumerateTextElements(from textLocation: NSTextLocation?, options: NSTextContentManager.EnumerationOptions = [], using block: (NSTextElement) -> Bool) -> NSTextLocation? from NSTextElementProvider.

The NSTextElement that I pass into the block uses a custom subclass to NSTextLocation. But, TextKit crashes with a cyrptic Thread 1: "-[NSCountableTextLocation compare:] receiving unmatching type (6, 1). The unmatching type indicated is an instance of my custom NSTextLocation (which I take should be the only type being used for comparison). I am at a loss as to where the NSCountableTextLocation is coming from. It's a private class, so, I can't create it either. Does TextKit create some kind of default in certain scenarios?

The other methods that I have over ridden from NSTextElementProvider are

func location(NSTextLocation, offsetBy: Int) -> NSTextLocation? func offset(from: NSTextLocation, to: NSTextLocation) -> Int

Neither of these seem to be involved during the crash.

Any ideas on how I could approach fixing this? Thanks

Update:

The entire stack trace if it helps is

-[NSCountableTextLocation compare:] receiving unmatching type (6, 1)
(
    0   CoreFoundation                      0x000000018cacc8c0 __exceptionPreprocess + 176
    1   libobjc.A.dylib                     0x000000018c5c5eb4 objc_exception_throw + 60
    2   CoreFoundation                      0x000000018cacc7b0 +[NSException exceptionWithName:reason:userInfo:] + 0
    3   UIFoundation                        0x00000001916382e8 -[NSCountableTextLocation compare:] + 204
    4   UIFoundation                        0x00000001915f3224 __90-[_NSTextLayoutFragmentStorage enumerateTextLayoutFragmentInTextRange:options:usingBlock:]_block_invoke + 204
    5   UIFoundation                        0x00000001915b3d7c __69-[_NSTextRunStorage enumerateObjectsFromLocation:options:usingBlock:]_block_invoke.21 + 224
    6   UIFoundation                        0x00000001915b35fc -[_NSTextRunStorage _performCountableRunStorageOperation:] + 80
    7   UIFoundation                        0x00000001915b372c -[_NSTextRunStorage enumerateObjectsFromLocation:options:usingBlock:] + 220
    8   UIFoundation                        0x00000001915f30b4 -[_NSTextLayoutFragmentStorage enumerateTextLayoutFragmentInTextRange:options:usingBlock:] + 356
    9   UIFoundation                        0x00000001915873c4 __NSTextLayoutManagerFillSoftInvalidationToLocation + 948
    10  UIFoundation                        0x0000000191587a4c -[NSTextLayoutManager updateLayoutWithTextLayoutFragment:addition:] + 1124
    11  UIFoundation                        0x00000001915c7e08 -[NSTextLayoutFragment _layout] + 2256
    12  UIFoundation                        0x000000019158a924 __83-[NSTextLayoutManager enumerateTextLayoutFragmentsFromLocation:options:usingBlock:]_block_invoke.175 + 296
    13  CoreFoundation                      0x000000018ca4b258 __NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    14  CoreFoundation                      0x000000018ca61af0 -[__NSSingleObjectArrayI enumerateObjectsWithOptions:usingBlock:] + 92
    15  UIFoundation                        0x000000019158a6b4 __83-[NSTextLayoutManager enumerateTextLayoutFragmentsFromLocation:options:usingBlock:]_block_invoke + 1436
    16  RMTextViewAppKitDemo                0x000000010281e8c0 $sSo13NSTextElementC10ObjectiveC8ObjCBoolVIyByd_ABSbIeggd_TR + 32
    17  RMTextViewAppKitDemo                0x000000010281cebc $s10RMTextView014RMMarkdownTextB5ModelC09enumerateD8Elements4from7options5usingSo14NSTextLocation_pSgAI_So0K32ContentManagerEnumerationOptionsVSbSo0K7ElementCXEtF + 4388
    18  RMTextViewAppKitDemo                0x000000010281e86c $s10RMTextView014RMMarkdownTextB5ModelC09enumerateD8Elements4from7options5usingSo14NSTextLocation_pSgAI_So0K32ContentManagerEnumerationOptionsVSbSo0K7ElementCXEtFTo + 96
    19  UIFoundation                        0x0000000191589f60 -[NSTextLayoutManager enumerateTextLayoutFragmentsFromLocation:options:usingBlock:] + 832
    20  UIFoundation                        0x0000000191590558 -[NSTextLayoutManager enumerateViewportElementsFromLocation:options:usingBlock:] + 100
    21  UIFoundation                        0x000000019161fb54 -[NSTextViewportLayoutController layoutViewport] + 988
    22  RMTextViewAppKitDemo                0x0000000102836bbc $s10RMTextView0A10ControllerC14layoutViewportyyF + 260
    23  RMTextViewAppKitDemo                0x0000000102843768 $s10RMTextView0aB10ControllerC15layoutSublayers2ofySo7CALayerC_tF + 252
    24  RMTextViewAppKitDemo                0x00000001028437d0 $s10RMTextView0aB10ControllerC15layoutSublayers2ofySo7CALayerC_tFTo + 52
    25  AppKit                              0x000000019085f928 -[NSViewBackingLayer layoutSublayers] + 120
    26  QuartzCore                          0x0000000194aeed4c _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 520
    27  QuartzCore                          0x0000000194c72c64 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 500
    28  QuartzCore                          0x0000000194ad2658 _ZN2CA11Transaction6commitEv + 648
    29  AppKit                              0x0000000190359298 __62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke + 272
    30  AppKit                              0x0000000190cf73c8 ___NSRunLoopObserverCreateWithHandler_block_invoke + 64
    31  CoreFoundation                      0x000000018ca570cc __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36
    32  CoreFoundation                      0x000000018ca56fb8 __CFRunLoopDoObservers + 532
    33  CoreFoundation                      0x000000018ca565e8 __CFRunLoopRun + 776
    34  CoreFoundation                      0x000000018ca55c2c CFRunLoopRunSpecific + 608
    35  HIToolbox                           0x0000000196fae448 RunCurrentEventLoopInMode + 292
    36  HIToolbox                           0x0000000196fae0d8 ReceiveNextEventCommon + 220
    37  HIToolbox                           0x0000000196fadfdc _BlockUntilNextEventMatchingListInModeWithFilter + 76
    38  AppKit                              0x0000000190230f90 _DPSNextEvent + 660
    39  AppKit                              0x0000000190a04b94 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 716
    40  AppKit                              0x000000019022443c -[NSApplication run] + 476
    41  AppKit                              0x00000001901fb708 NSApplicationMain + 880
    42  RMTextViewAppKitDemo                0x00000001027ed9e4 $sSo21NSApplicationDelegateP6AppKitE4mainyyFZ + 40
    43  RMTextViewAppKitDemo                0x00000001027ed9ac $s20RMTextViewAppKitDemo0C8DelegateC5$mainyyFZ + 44
    44  RMTextViewAppKitDemo                0x00000001027eda4c main + 28
    45  dyld                                0x000000018c601058 start + 2224
)
Message from debugger: killed

Update 2

The crash seems to be occurring during typing multiple paragraphs. I'm assuming it has something to do with multiple paragraphs. But, I can't say for sure. Would appreciate any input that would help me fix this.

Sample project that simulates the conditions leading to crash. Typing is simulated by extending documentRange of fullText, character by character at the end of layout.

Update 3

The code seems to crash on macOS Sonoma (14.2.1 23C71) with Xcode 15 and 15.2. As advised by somebody on another forum, it doesn't crash on Monterrey (12.6.1) with Xcode 14.2, or Ventura (13.6) with Xcode 15.2.

Update 4

To provide context on expected output, it should be

First

Second

Third

On Sonoma, the output is

First

Second

T

It crashes at the 'h' position, while laying out the NSTextElement corresponding to the second paragraph namely Second\n\n. It makes no difference if I put the second \n in a paragraph of it's own (still crashes). The exact same NSTextElement is laid out correctly at the T position.

0

There are 0 best solutions below