Search code examples
cloudkitappkit

NSSharingService creates "frozen" modal window for CKShare


I'm trying to present info about a CKShare to a user. You can do this as follows:

let container: CKContainer = /* existing CKContainer */
let share: CKShare = /* existing CKShare */

let item = NSItemProvider()
item.registerCloudKitShare(share, container: container)

let sharingService = NSSharingService(named: .cloudSharing)
sharingService.perform(withItems: [item])

This correctly opens the window:

ckshare-window

However, I cannot click anything in the window, and after closing the window I cannot click anything in my app.

EDIT: after further investigation, I realized I can navigate the UI using the keyboard. However, it is still quite buggy (triggering Done or pressing esc dismisses the view controller but doesn't close the window, and throws an NSInternalInconsistencyException)

The stack trace (below) shows that the main thread is waiting for events in the modal event loop:

#0  0x00007fff7de8b20a in mach_msg_trap ()
#1  0x00007fff7de8a724 in mach_msg ()
#2  0x00007fff55ef9785 in __CFRunLoopServiceMachPort ()
#3  0x00007fff55ef8ad7 in __CFRunLoopRun ()
#4  0x00007fff55ef8153 in CFRunLoopRunSpecific ()
#5  0x00007fff551e2d96 in RunCurrentEventLoopInMode ()
#6  0x00007fff551e2b06 in ReceiveNextEventCommon ()
#7  0x00007fff551e2884 in _BlockUntilNextEventMatchingListInModeWithFilter ()
#8  0x00007fff53493a73 in _DPSNextEvent ()
#9  0x00007fff53c29e34 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#10 0x00007fff536c5e7b in -[NSApplication _doModalLoop:peek:] ()
#11 0x00007fff538aac9f in __35-[NSApplication runModalForWindow:]_block_invoke_2 ()
#12 0x00007fff538aac4c in __35-[NSApplication runModalForWindow:]_block_invoke ()
#13 0x00007fff53d59219 in _NSTryRunModal ()
#14 0x00007fff536c3911 in -[NSApplication runModalForWindow:] ()
#15 0x00007fff53fc4289 in __87-[_NSCloudSharingService _showParticipantListServiceInSheetAttachedToWindow:withItems:]_block_invoke ()
#16 0x00007fff7a9ef0f4 in -[NSRemoteView _completeAdvanceToRunPhase:withError:] ()
#17 0x00007fff7a9d3c69 in __35-[NSRemoteView _advanceToRunPhase:]_block_invoke.1071 ()
#18 0x00007fff55ef5bec in __invoking___ ()
#19 0x00007fff55ef5ac0 in -[NSInvocation invoke] ()
#20 0x00007fff7aa172d2 in withHintInProgress ()
#21 0x00007fff7a98e792 in __deferNSXPCInvocationOntoMainThread_block_invoke ()
#22 0x00007fff7aa1cb9d in __wrapBlockWithVoucher_block_invoke ()
#23 0x00007fff7a98e36f in __deferBlockOntoMainThread_block_invoke_2 ()
#24 0x00007fff55f1687c in __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ ()
#25 0x00007fff55ef9253 in __CFRunLoopDoBlocks ()
#26 0x00007fff55ef9018 in __CFRunLoopRun ()
#27 0x00007fff55ef8153 in CFRunLoopRunSpecific ()
#28 0x00007fff7aa1690e in __invokeRunLoopInModeForDuration_block_invoke_2 ()
#29 0x00007fff7aa16862 in invokeRunLoopInModeForDuration ()
#30 0x00007fff7a9f371b in __29-[NSCFRunLoopSemaphore wait:]_block_invoke_2 ()
#31 0x00007fff7a9f3641 in __29-[NSCFRunLoopSemaphore wait:]_block_invoke ()
#32 0x00007fff7a9f2aac in +[NSCFRunLoopSemaphore _observe:whilePerforming:] ()
#33 0x00007fff7a9f332e in -[NSCFRunLoopSemaphore wait:] ()
#34 0x00007fff7a9cb9ed in -[NSRemoteViewSemaphore wait:] ()
#35 0x00007fff7a9d43db in -[NSRemoteView _waitOnSemaphore:] ()
#36 0x00007fff7a9e95a6 in -[NSRemoteView _didSetOriginOrSize:] ()
#37 0x00007fff7a9e9a7f in -[NSRemoteView setFrameSize:] ()
#38 0x00007fff7aa146e9 in withImplicitAnimation ()
#39 0x00007fff7a9e0184 in -[NSRemoteView _serviceRequestsResize:completion:] ()
#40 0x00007fff7a9e093e in -[NSRemoteView _serviceRequestsResize:animate:transaction:completion:] ()
#41 0x00007fff7a993ec4 in -[NSRemoteViewMarshal serviceRequestsResize:animate:transaction:completion:] ()
#42 0x00007fff55ef5bec in __invoking___ ()
#43 0x00007fff55ef5ac0 in -[NSInvocation invoke] ()
#44 0x00007fff7aa172d2 in withHintInProgress ()
#45 0x00007fff7a98e83e in __deferNSXPCInvocationOntoMainThread_block_invoke ()
#46 0x00007fff7aa1cb9d in __wrapBlockWithVoucher_block_invoke ()
#47 0x00007fff7a98e36f in __deferBlockOntoMainThread_block_invoke_2 ()
#48 0x00007fff55f1687c in __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ ()
#49 0x00007fff55ef9253 in __CFRunLoopDoBlocks ()
#50 0x00007fff55ef9018 in __CFRunLoopRun ()
#51 0x00007fff55ef8153 in CFRunLoopRunSpecific ()
#52 0x00007fff551e2d96 in RunCurrentEventLoopInMode ()
#53 0x00007fff551e2b06 in ReceiveNextEventCommon ()
#54 0x00007fff551e2884 in _BlockUntilNextEventMatchingListInModeWithFilter ()
#55 0x00007fff53493a73 in _DPSNextEvent ()
#56 0x00007fff53c29e34 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#57 0x00007fff53488885 in -[NSApplication run] ()
#58 0x00007fff53457a72 in NSApplicationMain ()
#59 0x000000010000d831 in main() at main.swift:25
#60 0x000000010000d324 in main at main.swift:28
#61 0x00007fff7dd44015 in start ()
#62 0x00007fff7dd44015 in start ()

Does anyone know how to fix this issue?


Solution

  • Had the same problem in an Objective-C project and found I needed to use the NSSharingServiceDelegate method to return the source Window.

    - (NSWindow *)sharingService:(NSSharingService *)sharingService sourceWindowForShareItems:(NSArray *)items sharingContentScope:(NSSharingContentScope *)sharingContentScope{
    
        return self.view.window;
    
    }
    

    https://developer.apple.com/documentation/appkit/nssharingservicedelegate/1402679-sharingservice

    [NSSharingService performWithItems:NSArrayOfItems]; on the main thread would then present a sheet that functions correctly.

    If from the owners privateCloudDatabase you would be presented all participants with sharing options, and like your screenshot, reduced participant options including ‘Remove Me’ if the shared record resides in the sharedCloudDatabase.