1
votes

I am trying to utilize CloudKit in my iOS application, but when I attempt to create a new record for for a User record type (record type is named Users), I get this error:

<CKError 0x7fb80947ffb0: "Permission Failure" (10/2007);
server message = "CREATE operation not permitted";
uuid = 8C4C7B60-E3F4-42FC-9551-D3A76A6FF9D6;
container ID = "iCloud.com.jojodmo.Blix">

To create the new record, I am using this code in viewDidLoad():

UserCKManager.create(
    CloudKitUser(
        email: "[email protected]", password: "password", salt: "1AF4E759B20FEC32",
        username: "jojodmo", posts: [], biography: "This is my bio",
        firstName: "John", lastName: "Doe", flags: [],
        profilePicture: UIImage(), downVotesGiven: 1, downVotesRecieved: 2,
        upVotesGiven: 3, upVotesRecieved: 4, pictureProvided: false), callback: nil)

Which creates a new CloudKitUser:

init(email: String, password: String, salt: String, username: String, posts: [String], biography: String, firstName: String, lastName: String, flags: [String], profilePicture: UIImage, downVotesGiven: Int, downVotesRecieved: Int, upVotesGiven: Int, upVotesRecieved: Int, pictureProvided: Bool){ 
    self.ready = false
    record = CKRecord(recordType: "Users")
    self.email = email
    self.password = password
    self.salt = salt
    self.username = username
    self.posts = posts
    self.biography = biography
    self.firstName = firstName
    self.lastName = lastName
    self.flags = flags
    self.profilePicture = profilePicture
    self.downVotesGiven = downVotesGiven
    self.downVotesRecieved = downVotesRecieved
    self.upVotesGiven = upVotesGiven
    self.upVotesRecieved = upVotesRecieved
    self.pictureProvided = pictureProvided
    self.ready = true
}

And then attempts to create a record with it:

class func create(user: User, callback: ((success: Bool, user: User?) -> ())?){
    let ckUser = CloudKitUser(user: user)
    //I've also tried using CKContainer.defaultContainer().privateCloudDatabase, and I get the same error
    CKContainer.defaultContainer().publicCloudDatabase.saveRecord(ckUser.record){(record, error) in
        if(error != nil){
            println("An error occurred: \(error)")
            callback?(success: false, user: nil)
        }
        else{
            println("Record saved successfully")
            callback?(success: true, user: ckUser)
        }
    }
}

I know it isn't a problem with connecting to the database, because I have already gotten an error saying that there was no container with the ID I had given, which I fixed.

I am trying to run this on the iOS simulator (I am signed into iCloud on it)

2
This seems to be a permission problem. Can you access the database directly with the same user? If so, can you create your record with direct access? I believe the answer for the first is yes and for the second is no. You need to give the database user create permission.Lajos Arpad
@LajosArpad The first answer IS yes, but the second answer IS also no, how can I give the database user create permission? I feel like I would have tried that if I knew howJojodmo
Possible answer could be setting the create permissions described here: stackoverflow.com/a/56733008/1807644William T.

2 Answers

2
votes

Users is a special recordType that already exist in CloudKit. You should not create records yourself. Records will be automatically created for new users that are using your app. You also can't create subscriptions and query the Users recordtype. You can only query Users records directly by ID. You can store extra data in the Users recordType, but I think in your case it would be better if you named your record type something else.

1
votes

In addition to Edwin's answer, it's entirely feasible to save custom fields to the public Users recordType, but you need to retrieve the CKRecordID for the user first (via CKContainer fetchUserRecordID() or discoverUserIdentity()) and then build the CKRecord on Users using that ID.

Also, if you're using CKModifyRecordsOperation make sure the savePolicy is set to .changedKeys in order to allow the update to go through.