iosswiftcloudkitios17

How to fetch User first and last name?


I attempted to retrieve the first name and last name of the current user from CloudKit. However, I received a message from Xcode indicating that the 'userDiscoverability' feature will be deprecated in iOS 17.0. This feature is no longer supported, and instead, I should consider using the "Sharing CloudKit Data with Other iCloud Users" feature.

Here's the function I've been using:

 func fetchUserName(completion: @escaping ( _ fullName:String, _ success:Bool) -> Void) {
        container.requestApplicationPermission(.userDiscoverability) { (status, error) in
            self.container.fetchUserRecordID { (record, error) in
                self.container.discoverUserIdentity(withUserRecordID: record!) { (userID, error) in
                    var name: String = ""
        
                    self.container.accountStatus { accountStatus, error in
                        if let error = error {
                            print(error.localizedDescription)
                        }
                        
                    }

                    guard let givenName = userID?.nameComponents?.givenName,
                          let familyName = userID?.nameComponents?.familyName else {
                        completion("", false)
                        print("Unable to fetch user name")
                        return
                    }
                    
                    let fullName: String = givenName + " " + familyName
                    name = fullName

                    DispatchQueue.main.async {
                        completion(name, true)
                    }
                }
            }
        }
    }

Does anyone have a solution on how to resolve this issue?


Solution

  • You no longer need the outer call (container.requestApplicationPermission).

    In order to retrieve the name, you'll need to first get active user record ID, then fetch the share participant, using the ID, and finally retrieve the name from the CKShare.Participant object. Your code already does this, and a modified version of it would look like:

     func fetchUserName(completion: @escaping ( _ fullName:String, _ success:Bool) -> Void) {
            self.container.fetchUserRecordID { (record, error) in
                self.container.fetchShareParticipant(withUserRecordID: record!) { (userID, error) in
                    var name: String = ""
            
                    self.container.accountStatus { accountStatus, error in
                        if let error = error {
                            print(error.localizedDescription)
                        }
                            
                    }
    
                    guard let givenName = userID?.nameComponents?.givenName,
                          let familyName = userID?.nameComponents?.familyName else {
                        completion("", false)
                        print("Unable to fetch user name")
                        return
                    }
                        
                    let fullName: String = givenName + " " + familyName
                    name = fullName
    
                    DispatchQueue.main.async {
                        completion(name, true)
                    }
                }
            }
        }
    

    If not already enabled, you will also need to enable CloudKit in your app.