check if firebase write operation was successful in iOS - ios

How to check if firebase real time write operation was successful in ios?
I am trying to store data to real time database using the following code but it does not work:-
//adding the artist inside the generated unique key
refArtists.child(key!).setValue(data) { (error, dbreference) in
if error != nil{
print(error?.localizedDescription)
} else {
print("success", dbreference)
}
}
and I also tried following:-
let key = refArtists.childByAutoId().key
//creating artist with the given values
let artist = ["id":key,
"latitude": "34234" as String,
"longitude": "67657" as String
]
let data = ["data": artist]
refArtists.child(key!).setValue(data)
I am unable to understand why my write operation is unsuccessful.
Edit from comments:
The closure does not get called. I am getting this error :
Firebase Database connection was forcefully killed by the server. Will not attempt reconnect. Reason: Firebase error. Please ensure that you spelled the name of your Firebase correctly.

Related

App crashing while trying to store data on Firestore

App Crashing with error:
FIRESTORE INTERNAL ASSERTION FAILED: Invalid document reference. Document references must have an even number of segments, but users_table has 1
I am trying to store like this:-
func updateFirestorePushTokenIfNeeded() {
if let token = Messaging.messaging().fcmToken {
let usersRef = Firestore.firestore().collection("users_table").document(userID)
usersRef.setData(["fcmToken": token], merge: true)
}
}
My firestore is empty right now.
That error message almost certainly means that userID is nil or empty. You should verify that you're passing the correct values to Firestore.

error creating object using Firebase values

I am attempting to pull down information from my Firebase database and use it to create an object of type Order. The error that I have printed in the catch statement is as follows.
Error Domain=myProjectName.OrderError Code=0 "(null)"
I am unsure what this means exactly, or how to fix it.
I have defined a custom error type in my Order class, as shown below.
enum OrderError: ErrorType
{
case IllegalOrderNumber
case InvalidEntry
}
The error is generated by the following code snippet.
self.ref.child("orders").observeEventType(.ChildAdded, withBlock: { (snapshot) in
let pickupLoc = snapshot.value!["pickupLocation"] as? String
let dropoffLoc = snapshot.value!["dropoffLocation"] as? String
let orderNumInt = snapshot.value!["orderNum"] as? Int
//since the database will return nil if you try and cast a string to an int
//we get it as an int then cast to string
let orderNum = String(orderNumInt)
do
{
let myOrder = try Order(PickUpLoc: pickupLoc, DropOffLoc: dropoffLoc, OrderNum: orderNum)!
self.orders.append(myOrder)
}
catch let error as NSError
{
//should never get here
print(error)
}
})
I do all of the error checking when the user enters the value into the database, so there should be no reason for there to be an error generated.
Okay, so after combing through my code I noticed two primary possible error sources. Firstly, despite the compiler not complaining, the do-catch block was not exhaustive, and therefore an additional catch was added to fix this. Secondly, I believe the error was generated by the fact that I declared my Orders array as var orders = [Order()] as opposed to var orders = [Order](), when I changed this, the program ran smoothly.

CloudKit Error Differentiation

I need some help to learn how to properly handle errors when fetching records via CloudKit. Currently I have an app that saves numerous records in the cloud, and will load them at launch. I have been referencing the records using a CKReference, and anytime I save the reference I use the CKReferenceAction.DeleteSelf option. A problem I've encountered periodically is that when a referenced record is deleted, sometimes there can be a significant amount of time before the reference deletes itself. This has caused me to occasionally come across the situation where my app has fetched a CKReference for a record that no longer exists. I'm able to manually find out when this happens just by inserting print(error!) in my error handler. What I would like to know is how I can add some code to detect this specific error i.e. if error.localizedDescription == ??? {.
Here is the basic code I'm using for the fetch:
let fetch = CKFetchRecordsOperation(recordIDs: recordIDs)
fetch.perRecordCompletionBlock = { (record:CKRecord?, recordID:CKRecordID?, error: NSError?) in
if error != nil {
// Error Line A (See below)
print("ERROR! : \(error!.localizedDescription)")
// Error Line B (See below)
print("ERROR: \(error!)")
}
else if let record = record {
// Record was found
}
}
if let database = self.privateDatabase {
fetch.database = database
fetch.start()
}
And then when it tries to fetch the non-existent record, here is the error message that prints out in the compiler window:
a) ERROR! : Error fetching record <CKRecordID: 0x10025b290; dbbda7c3-adcc-4271-848f-6702160ea34f:(_defaultZone:__defaultOwner__)> from server: Record not found
b) ERROR: <CKError 0x125e82820: "Unknown Item" (11/2003); server message = "Record not found"; uuid = (removed); container ID = "(removed)">
Above in error line B, where it says CKError 0x125e82820:, can I use this to create an if statement to check for this specific error type? I really could use any help finding a way to resolve this issue properly when it happens. I have set up some loading structure for my app, and when it thinks there is a record it needs to find, but can't, it screws up my loading process. I would really appreciate any help I can get, I assume it's an easy solution, but apparently not one I've been able to find. Thank you!
UPDATE -
Thanks to #AaronBrager, I was able to find the correct solution. You can verify the error code to match it to any specific error, and the domain to make sure it's a CKError. Here is the solution that works for me:
let fetch = CKFetchRecordsOperation(recordIDs: recordIDs)
fetch.perRecordCompletionBlock = { (record:CKRecord?, recordID:CKRecordID?, error: NSError?) in
if error != nil {
if error!.code == CKErrorCode.UnknownItem.rawValue && error!.domain == CKErrorDomain {
// This works great!
}
}
else if let record = record {
// Record was found
}
}
if let database = self.publicDatabase {
fetch.database = database
fetch.start()
}
You should be able to uniquely identify an error's cause by inspecting its domain and code variables. Same domain and code, same problem. And unlike localizedDescription, it won't change between users.

Parse query on array of pointers only retrieving first object

In the code below, self.arrayOfLikers is an array of Pointers to Parse User Objects. Which looks like this on Parse:
var query = PFQuery(className: "Item")
query.includeKey("likedBy")
query.getObjectInBackgroundWithId(theObjectIdOfTheItem!) { (returnedItem, error) in
if error != nil {
print(error)
}
else {
returnedItem?.fetchInBackgroundWithBlock({ (fetchedReturnedItem, error) in
if error != nil {
print(error)
}
else {
dispatch_async(dispatch_get_main_queue(),{
self.arrayOfLikers = fetchedReturnedItem!["likedBy"] as! [PFUser]
print("about to print the arrayOfLikers")
print(self.arrayOfLikers)
self.tableView.reloadData()
})
}
})
}
}
When I print my self.arrayOfLikers I can see that the first index contains a correctly retrieved PFUser object. Below is a print statement from Xcode:
In another viewController, I am storing these pointers when the user taps the "like" button. This is how I am storing those pointers:
Creation of the userPointer:
let userPointer = PFObject(outDataWithClassName: "User", objectId: user?.objectId)
(oddly, the Parse docs use withoutDataWithClassName, but when I put this in, Xcode keeps making me change it outDataWithClassName, and it compiles, so I guess this is correct?)
Storing the userPointer: (please note, theItemObject is an object set by a previous VC):
theItemObject!.addObject(userPointer, forKey: "likedBy")
Consequently, Parse via Xcode gives me this error:
2016-03-30 23:38:47.749 Trashly[5482:1512409] [Error]: object not found for get (Code: 101, Version: 1.12.0)
Optional(Error Domain=Parse Code=101 "object not found for get" UserInfo={code=101, temporary=0, error=object not found for get, NSLocalizedDescription=object not found for get})
Any ideas why my query is not getting any user objects but the first one?

Cloudant does not not store object data sent via Bluemix "Data for iOS 8"

I am trying to store a simple object (a custom class that has two String properties) in a Cloudant DB from an iOS App. I am making use of the Bluemix iOS SDK, specifically "Data for iOS 8". So far I am trying to apply the samples for the Swift programming language from the IBM Bluemix documentation.
The code to store an object is from the tutorials and has been only slightly adapted, if at all. The code below is contained in a function that is called when a text field's edit is done.
var remoteStore:CDTStore!
// initialize an instance of the IMFDataManager
let manager:IMFDataManager = IMFDataManager.sharedInstance()
let name = "pricingdb"
var testData = TestData(firstName: "aaaa", lastName: "bbbbb")
// Create remote store
manager.remoteStore(name, completionHandler: { (createdStore:CDTStore!, error:NSError!) -> Void in
if nil != error {
//Handle error
} else {
remoteStore = createdStore
println("Successfully created store: \(remoteStore.name)")
// Register class with remote store
remoteStore.mapper.setDataType("TestData", forClassName: NSStringFromClass(TestData.classForCoder()))
// Actually save the object to Bluemix
remoteStore.save(testData, completionHandler: { (savedObject:AnyObject!, error:NSError!) -> Void in
if nil != error {
//Save was not successful, handler received an error
println("Error: \(error)")
} else {
// Use the result
println("Saved revision: \(savedObject)")
}
})
}
})
The Cloudant database I want to store to exists. I can connect to the Datastore and the object is as well saved, the console output is:
HTTP_Status: 201
JSON Body: {
id = 6dfde55449915faa92c471bd0ecd89d6;
ok = 1;
rev = "1-419dfa2a14026c4c18545723e8f990fa";
}
Saved revision: <pricingtester.TestData: 0x7f91f1c6e2f0>
However, when looking at the JSON Body above I would expect to see the object data in there and, even if it wouldn't/shouldn't show there, I would expect to see it in the database entry that was created. But the corresponding database entry when checking the Cloudant dashboard is as follows:
{
"_id": "6dfde55449915faa92c471bd0ecd89d6",
"_rev": "1-419dfa2a14026c4c18545723e8f990fa",
"#datatype": "TestData"
}
What could I be missing?
A related question came up:
In the code above, the store is always created. If it exists, it is not recreated, but a reference to that store is made. If I know the store exists, which it does, how can I obtain a reference to that store without trying to first create it?
Can you provide the source code for the TestData class? For swift classes, String must currently use the NSString (ObjC) instead of the Swift String (e.g. var make:NSString)

Resources