How do I get user record in CloudKit? - ios

I can fetch the userRecordID, but I get an error whenever I try to fetch the record associated with that ID. Any suggestions? Code and error below:
myContainer.fetchUserRecordID { (thisID, thisError) in
if let userError = thisError {
print("DEBUG: error getting user id; \(userError)")
} else {
if let userID = thisID {
self.publicDatabase.fetch(withRecordID: userID, completionHandler: { (fetchedUser, fetchedError) in
if let thisError = fetchedError {
print("DEBUG: error getting user record; \(thisError)")
}
DEBUG: error getting user record; <CKError 0x174045010: "Internal Error" (1/5001); "Couldn't get a PCS object to unwrap encrypted data for field encryptedPublicSharingKey: (null)">
Error in the code, or my fault for trying beta software (iOS 10, Swift 3 & xCode-beta 8.0 beta 2 (8S162m)

From your example it is not clear if self.publicDatabase is equal to myContainer.publicCloudDatabase.
Make sure you fetch it from the same container's database, otherwise it will obviously not work.
myContainer.fetchUserRecordID { userID, error in
guard error == nil else {
print("DEBUG: error getting user id; \(userError)")
return
}
guard let userRecID = userID else {
print("DEBUG: Can't unwrap userID")
return
}
myContainer.publicCloudDatabase.fetch(withRecordID: userRecID, completionHandler: { (fetchedUser, fetchedError) in
//handle the error and the user
print("DEBUG: User fetch FINISHED!", fetchedUser)
})
}

I needed to change from publicDatabase to privateDatabase.
self.publicDatabase.fetch(withRecordID: userID, completionHandler: { (fetchedUser, fetchedError) in
to
self.privateDatabase.fetch(withRecordID: userID, completionHandler: { (fetchedUser, fetchedError) in

Related

saveInBackground (Parse) throwing an error

I am having an issue in the following swift code, using Parse-Server to save data online.
let xxDico = ["N8": "Eight", "N5": "Five"],
upLoadParseUnit = PFObject(className: "numberClass",
dictionary: xxDico)
print("xxDico : \(xxDico.count)")
upLoadParseUnit.saveInBackground {
(succeeded:Bool, error:Error?) in
if succeeded {
print("\(#function) succeeded!!")
} else {
if error?.localizedDescription == "NAME-USED" {
// A record previously existed with the same name.
print("\(#function) did not succeeded!!\nError: \(error?.localizedDescription)")
return
}
print("Error(1) in \(#function)\n" + (error?.localizedDescription)!)
}
}
And this is what I get in the debugging console:
xxDico : 2
Error(1) in executeUpLoad(_:)
The data couldn’t be read because it isn’t in the correct format.
This seems simple, but what am I doing wrong to get this error?
And what am I supposed to do?

callkit reload extension in ios

i am creating app like as trucaller. Everything is completed, only one issue remaining. issue is that how to reload application extension after add new contact number from server in app. first of all, i enter some static number in the array then after i store it in userdefault. i got this by app-groups functionality. i want that when user synchronize their contact in my application, i want reload contact list.
this is my code
manager.reloadExtension(withIdentifier: extensionIdentifer, completionHandler: { error in
print("error \(error?.localizedDescription)")
if let _ = error{
print("A error \(error?.localizedDescription as String!)");
}
})
this is give me error like below
"sqlite3_step for query 'INSERT INTO PhoneNumberBlockingEntry
(extension_id, phone_number_id) VALUES (?, (SELECT id FROM PhoneNumber
WHERE (number = ?)))' returned 19 (2067) errorMessage 'UNIQUE
constraint failed: PhoneNumberBlockingEntry.extension_id,
PhoneNumberBlockingEntry.phone_number_id'"
Jaydeep: Call your new contact web service or synchronize contacts in application and just reload extension as -
CXCallDirectoryManager.sharedInstance.getEnabledStatusForExtension(withIdentifier: "com.compname.sampleapp", completionHandler: { (enabledStatus,error) ->
Void in if let error = error {
print(error.localizedDescription)
}
CXCallDirectoryManager.sharedInstance.reloadExtension(withIdentifier:"com.compname.sampleapp", completionHandler: {
(error) ->
Void in if let error = error {
print(error.localizedDescription)
}
DispatchQueue.main.async {
self.hud?.hide(animated: true)
}
})
print("No error")
})
Let me know still issue getting. I have done this and working fine.

CloudKit: Get users firstname/surname

I'm trying to get the users first name using cloud kit however the following code is not getting the users first name and is leaving firstNameFromFunction variable empty. Does anyone know how to achieve this in iOS 10?
let container = CKContainer.default()
container.fetchUserRecordID { (recordId, error) in
if error != nil {
print("Handle error)")
}else{
self.container.discoverUserInfo(
withUserRecordID: recordId!, completionHandler: { (userInfo, error) in
if error != nil {
print("Handle error")
}else{
if let userInfo = userInfo {
print("givenName = \(userInfo.displayContact?.givenName)")
print("familyName = \(userInfo.displayContact?.familyName)")
firstNameFromFunction = userInfo.displayContact?.givenName
}else{
print("no user info")
}
}
})
}
}
the permission screen that comes up when asking for the first time, IMO, is very poorly worded. They need to change that. It says "Allow people using 'your app' to look you up by email? People who know your email address will be able to see that you use this app." This make NO sense. This has nothing to do with asking the user to get their iCloud first name, last name, email address.
Speaking of email address - this and the phone number from the lookupInfo property is missing - i.e. set to nil, even though those values are legit and correct. Filing a bug tonight.
First, you will need to request permission to access the user's information.
Then, you can use a CKDiscoverUserIdentitiesOperation. This is just like any other CKOperation (eg. the modify record operation). You just need to create a new operation with the useridentitylookupinfo. Then you will also need to create a completion block to handle the results.
Here is an example function I created:
func getUserName(withRecordID recordID: CKRecordID,
completion: #escaping (String) -> ()) {
if #available(iOS 10.0, *) {
let userInfo = CKUserIdentityLookupInfo(userRecordID: recordID)
let discoverOperation = CKDiscoverUserIdentitiesOperation(userIdentityLookupInfos: [userInfo])
discoverOperation.userIdentityDiscoveredBlock = { (userIdentity, userIdentityLookupInfo) in
let userName = "\((userIdentity.nameComponents?.givenName ?? "")) \((userIdentity.nameComponents?.familyName ?? ""))"
completion(userName)
}
discoverOperation.completionBlock = {
completion("")
}
CKContainer.default().add(discoverOperation)
} else {
// iOS 10 and below version of the code above,
// no longer works. So, we just return an empty string.
completion("")
}
}
First you need to ask the user for permission to be discovered.
Use CKContainer.default().requestApplicationPermission method passing .userDiscoverability on applicationPermission parameter.
The CKContainer.default().discoverUserInfo method is deprecated on iOS 10. Instead use CKContainer.default().discoverUserIdentity method.
Do something like:
CKContainer.default().requestApplicationPermission(.userDiscoverability) { (status, error) in
CKContainer.default().fetchUserRecordID { (record, error) in
CKContainer.default().discoverUserIdentity(withUserRecordID: record!, completionHandler: { (userIdentity, error) in
print("\(userIdentity?.nameComponents?.givenName)")
print("\(userIdentity?.nameComponents?.familyName)")
})
}
}

Fetching CloudKit User Record using UserRecordID

The question is to fetch data from User Records when UserRecordID is fetched.
Method to get User ID:
post.creatorUserRecordID?.recordName
My Users Record Type contains columns like username, so, I need to parse them for a concrete user. Is it possible somehow?
If I understood your question and you already have a CKRecordID. All you got to do then is to fetchRecordWithID using this CKRecordID you got.
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
publicDatabase.fetchRecordWithID(recordId, completionHandler: { (fetchRecord: CKRecord?, fetchError: NSError?) in
if let error = fetchError
{
// error getting user record, try again
print("-> cloudKitFetchUserRecord - error fetching user record - Error \(error)")
}
else
{
if let record = fetchRecord
{
if record.recordType == CKRecordTypeUserRecord
{
// valid record
print("-> cloudKitFetchUserRecord - fetching user record - valid record found - \(record.recordID.recordName))")
// unwrap your values - on your case username
if let object = record.objectForKey("username") as? Bool
{
// do something with object
}
}
else
{
// not valid record
print("-> cloudKitFetchUserRecord - fetching user record - The record that came back is not a CKRecordTypeUserRecord")
}
}
else
{
// record nil
print("-> cloudKitFetchUserRecord - fetching user record - fetch record returned nil")
}
}
})
It is simpler now using async/await in Swift 5
func getUserID() async {
let container = CKContainer(identifier: "iCloud.com.XXX.XXXX")
// CKContainer.defaultContainer().publicCloudDatabase // or default public container
do {
let userRecordID = try await container.userRecordID()
print("recordName: \(userRecordID.recordName)")
}
catch {
print("Error: \(error)")
}

Quick blox chat message sending response is success but messages are not delivered to server

Just working with Quick blox Chat API though its interesting and fun but stuck horribly when coming to sending messages successfully to group.
I first created a ChatDialog(not public group) and its created with out any problems.Now i want to send messages to the ChatDialog.
This is the code at Client side in Swift :
let user = QBUUser()
user.ID = (QBSession.currentSession().currentUser?.ID)!
user.password = "*********"
QBChat.instance().connectWithUser(user) { (error: NSError?) -> Void in
if error == nil{
print("Success in connection")
self.chatGroup = QBChatDialog(dialogID:self.selectedChatGroup.chatGroupId, type: QBChatDialogType.Group)
self.chatGroup.occupantIDs = self.selectedChatGroup.opponents
self.chatGroup.joinWithCompletionBlock { (err) in
if err == nil{
print("Joined Succesfully")
let message: QBChatMessage = QBChatMessage()
message.text = "PRAISE THE LORD"
message.deliveredIDs = [(QBSession.currentSession().currentUser?.ID)!]
message.readIDs = [(QBSession.currentSession().currentUser?.ID)!]
message.markable = true
self.chatGroup.sendMessage(message, completionBlock: { (error: NSError?) -> Void in
if err == nil{
print(message.text)
print("Message sent Succesfully")
let resPage = QBResponsePage(limit:20, skip: 0)
QBRequest.messagesWithDialogID(self.selectedChatGroup.chatGroupId, extendedRequest: nil, forPage: resPage, successBlock: {(response: QBResponse, messages: [QBChatMessage]?, responcePage: QBResponsePage?) in
print("Messages count is \(messages?.count)")
}, errorBlock: {(response: QBResponse!) in
})
}else{
print(err?.localizedDescription)
}
});
}
else{
print(err?.localizedDescription)
}
}
}
}
This is the Response that i am getting back.i am pretty sure that logging to chat, connecting to group are successful. Even from the response given back from the API is also affirming that sending message is successful.But i am not able to see any messages in the Admin Panel at Quick blox. And also tried getting all the messages from the Chat dialog but its giving 0 messages.So my messages are not getting delivered.
Yah, got the solution from Quickblox API.This is what i missed in my code.
var params = NSMutableDictionary()
params["save_to_history"] = true
message.customParameters = params
Worked like a charm!

Resources