Search code examples
iosfirebaseios-extensions

Firebase runTransactionBlock() in iOS share extension


My share extension has the following code as part of the didSelectPost() segment:

override func didSelectPost() {
    if self.sharedURL != nil {
            // Send data to Firebase
            self.myRootRef.runTransactionBlock({
                (currentData:FMutableData!) in
                var value = currentData.value as? String
                // Getting the current value
                // and checking whether it's null
                if value == nil {
                    value = ""
                }
                // Setting the new value to the clipboard
                // content
                currentData.value = self.sharedURL?.absoluteString

                // Finalizing the transaction
                return FTransactionResult.successWithValue(currentData)
                }, andCompletionBlock: {
                    // Completion Check
                    (error:NSError!, success:Bool, data:FDataSnapshot!) in
                    print("DEBUG- We're done:\(success) and \(error)")
                }
            )
        }

        // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
        // Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
        self.extensionContext!.completeRequestReturningItems([], completionHandler: nil)
}

I'm getting the following error at runtime:

host connection <NSXPCConnection: 0x7fb84af2e8c0> connection from pid 16743 invalidated

I believe this error is due to the andCompletionBlock and related to the following issue: Debug info when run today extension

How can I cleanly and successfully deal with the completion status of the above transaction?


Solution

  • Like the answer you linked to stated, the NSXPCConnection error doesn't matter here.

    The issue is that .runTransactionBlock() is asynchronous and .completeRequestReturningItems() will get called and exit the extension before you ever get a value from your Firebase database.

    Try running .completeRequestReturningItems() in the andCompletionBlock.

    override func didSelectPost() {
        if self.sharedURL != nil {
                // Send data to Firebase
                self.myRootRef.runTransactionBlock({
                    (currentData:FMutableData!) in
                    var value = currentData.value as? String
                    // Getting the current value
                    // and checking whether it's null
                    if value == nil {
                        value = ""
                    }
                    // Setting the new value to the clipboard
                    // content
                    currentData.value = self.sharedURL?.absoluteString
    
                    // Finalizing the transaction
                    return FTransactionResult.successWithValue(currentData)
                    }, andCompletionBlock: {
                        // Completion Check
                        (error:NSError!, success:Bool, data:FDataSnapshot!) in
                                self.extensionContext!.completeRequestReturningItems([], completionHandler: nil)
                    }
                )
            }
    
    }