Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

userDidAcceptCloudKitShareWith not being called

func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {...}

does not get called after clicking "OK" on the link to a shared cloudkit record. The app will open, but this function (which is supposed to be called) is not.

  • CKSharingSupported:YES is listed in my info.plist
  • I've put the record into a zone called "sharedZone"
  • SharedZone is showing up in my zone list, on my Private database.
  • The shared record shows me as being "invited"
  • Tried deleting app and cloud data and reinstalling, no change
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
        print("you accepted something")



        let acceptShareOperation: CKAcceptSharesOperation = CKAcceptSharesOperation(shareMetadatas:[cloudKitShareMetadata])

        //acceptShareOperation.qualityOfService = .userInteractive

        acceptShareOperation.perShareCompletionBlock = {meta, share,
            error in
            print("share was accepted")
        }

        acceptShareOperation.acceptSharesCompletionBlock = {
            error in
            /// Send your user to where they need to go in your app
            print("share accepted completion block!")
        }

        CKContainer(identifier: cloudKitShareMetadata.containerIdentifier).add(acceptShareOperation)
    }

Expected result: AT LEAST seeing the line "you accepted something" printed to the console.

UPDATE: Reverting back to IOS11.3 doesn't make it work.

UPDATE: I downloaded a tutorial someone had built that uses cloudkit and (after some finagling, got theirs to work. I then gutted their code and put mine in instead, and NOW the function works properly, so I think the issue may have something to do with either:

  • XCODE 11 beta, or
  • The new coredata + cloudkit syncing feature apple added.
like image 236
Eamonn Avatar asked Jul 19 '19 00:07

Eamonn


3 Answers

If you use fresh Xcode 11 project, there is SceneDelegate.swift. You need to implement there:

internal func windowScene(_ windowScene: UIWindowScene, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) { }

If you want to get userDidAcceptCloudKitShareWith called inside AppDelegate.swift you have to remove from Info.plist file next lines:

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <false/>
    <key>UISceneConfigurations</key>
    <dict>
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneConfigurationName</key>
                <string>Default Configuration</string>
                <key>UISceneDelegateClassName</key>
                <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                <key>UISceneStoryboardFile</key>
                <string>Main</string>
            </dict>
        </array>
    </dict>
</dict>

UPDATED

If you are trying to accept share on cold start using Scene Manifest, CKShare.Metadata will be passed to func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) in connectionOptions.

like image 192
Nikolay Tabunchenko Avatar answered Nov 07 '22 10:11

Nikolay Tabunchenko


To make this work you have to use SceneDelegate.

There are 3 steps to get scenedelegate working.

1 - Add Appdelegate

class AppDelegate: NSObject, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print("abc")
        return true
    }
}

Don't forget to use a delegate adaptor if you use SwiftUI way of entering the program.

    struct ExampleApp: App {
        @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
              MainView()
          }
    }

Also don't forget to add this to your appdelegate class:

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    
    if options.userActivities.first?.activityType == "newWindow" {
        let configuration = UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
        configuration.delegateClass = SceneDelegate.self
        return configuration
    } else {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }
    
}

2 - Configure info.plist to handle scenes through a SceneDelegate

add these to your info.plist

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <false/>
    <key>UISceneConfigurations</key>
    <dict>
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneConfigurationName</key>
                <string>Default Configuration</string>
                <key>UISceneDelegateClassName</key>
                <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
            </dict>
        </array>
    </dict>
</dict>

3 - Now add SceneDelegate and get the delegate callbacks that you need

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

        class SceneDelegate: UIResponder, UIWindowSceneDelegate {
            var window: UIWindow?
        
            func windowScene(_ windowScene: UIWindowScene, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
                print("abcd")
            }
    }

    }

note: in info.plist and in your appdelegate code there is a reference to "default configuration". You can change this to whatever you want (it's meant to enable management of more than one scene), but they should be the same off course.

like image 3
Cihan Avatar answered Nov 07 '22 08:11

Cihan


After 2 days of trial and error I got it working.

The issue seems to be related to Apples new Core Data + Cloudkit syncing abilities. They seem to gloss over the appdelegate function I need to call.

I fixed the issue by rebuilding the app in Xcode 10, then opening it in XCode 11 without changing anything. I'll let Apple know too.

Thank me. I'm welcome.

like image 1
Eamonn Avatar answered Nov 07 '22 08:11

Eamonn