8
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.
Eamonn
  • 161
  • 2
  • 7
  • "on the link to a shared cloudkit record" Where do we find the link? – El Tomato Jul 19 '19 at 00:48
  • When the "Share" UI comes up (apples built in one) it'll show a list of methods along the bottom: Mail, Whatsapp, Message, copy link. If you choose "copy link" the window will change to what looks like an email, allowing you to add contacts. At the top right, it'll say "copy link". Tapping that will put the link on your clipboard. I then open "messages" and paste the link in. It's an icloud link that looks something like "https://www.icloud.com/share/2949485r8959494#shareTitle", I then send that to my other account, and click the link on my other device. – Eamonn Jul 19 '19 at 01:06

3 Answers3

18

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.

  • If you implement option 1 it does not work when your app has a cold start. Do you know a solution for that as well? (I need the UIApplicationSceneManifest so I'm not able to remove this) – user1242574 Jan 20 '20 at 07:56
  • Did you ever find out how to ensure CKAcceptSharesOperation is called on an App that is not already running? CKAcceptSharesOperation on launch? – Rob Jan 20 '20 at 20:48
  • I'm using a SceneDelegate and at least in MacOS 10.15.3 and 10.15.4 Beta 1, my willConnectToSession is never invoked with connectionOptions.cloudKitShareMetadata and userDidAcceptCloudKitShareWith is never invoked at all. Both of them work exactly as desired on iOS. CKSharingSupported is true. And the app is correctly launched / activated when the link is clicked, so MacOS clearly knows which app should handle the CKShare. – LenK Feb 07 '20 at 19:01
  • How do you even learn of this stuff? You saved me 5 hours of time. Can you also explain what is the implication of removing that section in info.plist? – erotsppa Feb 16 '20 at 00:30
  • @erotsppa, the original question was: to get userDidAcceptCloudKitShareWith called in AppDelegate. But if project was created with Scene Manifest support, you would never get that call. Otherwise app will call similar method in your Scene Delegate. Though if you want to get it called in AppDelegate, you need to disable scene manifest support, by editing info.plist. – Nikolay Tabunchenko Feb 17 '20 at 15:40
3

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.

Cihan
  • 69
  • 1
  • 3
1

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.

Eamonn
  • 161
  • 2
  • 7
  • Sounds like your solution was similar to mine: https://stackoverflow.com/questions/50827303/cloudkit-ckshare-userdidacceptcloudkitsharewith-never-fires-on-mac-app – Clifton Labrum Jul 20 '19 at 15:52
  • I saw your post, yeah, but since you were working with a mac app I wasn't sure if the issues would be the same. I'm glad you didn't have to rebuild yours from scratch though! – Eamonn Jul 21 '19 at 13:37