Crash in dragImageForSelection(with:origin:)

I'm working on a rewrite of my app in Swift from an older mixed C/C++/Objective-C version, and I'm getting a crash when trying to create a drag image from an NSTextView. I have a custom view containing an NSTextView which is set up like this:


let textView = NSTextView(frame: textRect)
textView.drawsBackground = false
textView.isEditable = false
textView.isSelectable = false
textView.isVerticallyResizable = false
textView.isHorizontallyResizable = false
textView.selectedTextAttributes = [:]
addSubview(textView)


(I have tried isSelectable true and false, without change of behaviour). In the mouseDragged(with:) function, I have this code:


textView.setSelectedRange(NSMakeRange(0, textView.textStorage!.length))
let dragImage = textView.dragImageForSelection(with: event, origin: nil)
let dragItem = NSDraggingItem(pasteboardWriter: self)
dragItem.setDraggingFrame(NSMakeRect(0.0, 0.0, theRect.size.width, theRect.size.height), contents: dragImage)
beginDraggingSession(with: [dragItem], event: event, source: self)


I always get a crash in the call to dragImageForSelection(with:origin:):


2019-04-29 09:16:38.291806+0300 MyApp[61986:7244166] [General] Cannot lock focus on image <NSImage 0x6000018c4a80 Size={0, 0} Reps=(

) flipped:YES (flippedness is deprecated)>, because it is size zero.

2019-04-29 09:16:38.293248+0300 Ukelele Swift[61986:7244166] [General] (

0 CoreFoundation 0x00007fff3f3b5cf9 __exceptionPreprocess + 256

1 libobjc.A.dylib 0x00007fff69f4aa17 objc_exception_throw + 48

2 CoreFoundation 0x00007fff3f3b5b2b +[NSException raise:format:] + 201

3 AppKit 0x00007fff3caa9f17 -[NSImage _lockFocusOnRepresentation:rect:context:hints:flipped:] + 316

4 AppKit 0x00007fff3caa9dd1 __51-[NSImage lockFocusWithRect:context:hints:flipped:]_block_invoke + 68

5 AppKit 0x00007fff3ca3aa7b -[NSImage _usingBestRepresentationForRect:context:hints:body:] + 156

6 AppKit 0x00007fff3caa9d83 -[NSImage lockFocusWithRect:context:hints:flipped:] + 141

7 AppKit 0x00007fff3cbabfe5 -[NSImage lockFocusFlipped:] + 111

8 AppKit 0x00007fff3d1dfcdb -[NSTextView(NSDragging) dragImageForSelectionWithEvent:origin:] + 843

9 MyApp 0x000000010022070a $s13MyApp10MyViewC12mouseDragged4withySo7NSEventC_tF + 842

10 MyApp 0x0000000100220b2c $s13MyApp10MyViewC12mouseDragged4withySo7NSEventC_tFTo + 60

11 AppKit 0x00007fff3caf2b9f -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 6840

12 AppKit 0x00007fff3caf0e9f -[NSWindow(NSEventRouting) sendEvent:] + 478

13 AppKit 0x00007fff3c9906c3 -[NSApplication(NSEvent) sendEvent:] + 331

14 AppKit 0x00007fff3c97eee8 -[NSApplication run] + 755

15 AppKit 0x00007fff3c96e3f0 NSApplicationMain + 777

16 MyApp 0x00000001001a94dd main + 13

17 libdyld.dylib 0x00007fff6b7783d5 start + 1

18 ??? 0x0000000000000003 0x0 + 3

)


The Objective-C version is practically identical, and does not crash:


NSDraggingItem *dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter:self];
[self.textView setSelectedRange:NSMakeRange(0, [self.textView.textStorage length])];
NSImage *dragImage = [self.textView dragImageForSelectionWithEvent:theEvent origin:nil];
[dragItem setDraggingFrame:NSMakeRect(0.0, 0.0, theRect.size.width, theRect.size.height) contents:dragImage];
NSArray *dragItems = [NSArray arrayWithObject:dragItem];
[self beginDraggingSessionWithItems:dragItems event:theEvent source:self];


I've checked the NSTextView and it is correct, the selection is being set correctly, but the crash happens in the Swift version.


Has anybody got a clue how to fix this?


Thanks,

John

Accepted Reply

It seems as though I was stumbling into some sort of race condition (though everything was happening on the main thread). Responding to a click would trigger updating the window, and click and drag in one movement would make it fail. Click, hold and drag workes. Changing the way that the window was updated in these circumstances (not changing the string in the text field) seems to have cured the problem.

Replies

It seems as though I was stumbling into some sort of race condition (though everything was happening on the main thread). Responding to a click would trigger updating the window, and click and drag in one movement would make it fail. Click, hold and drag workes. Changing the way that the window was updated in these circumstances (not changing the string in the text field) seems to have cured the problem.