Firestore document creation fails without an error - ios

Edit3: Okay, it seems like it's an issue with Firebase, someone else tweeted about having the same issue. I also contacted support.
A piece of Swift code that handles creating documents suddenly stopped working. No errors are thrown, Firebase doesn't complain in the log and I can verify from the console that the document is not created, I can verify that the device has a healthy internet connection. I also disabled offline persistence for Firebase just to be sure.
When I try debugging it, the debugger jumps straight over the block that handles errors or successes, never running it (i.e. never finishing the Firestore request?).
Here is the code
func createConversation(){
let conversation : [String : Any] = ["owners" : [
UserProfile().getProfile().uid!],
"seeking" : true,
"timestamp" : Timestamp(date: Date())
]
var ref: DocumentReference? = nil
ref = DB().firestore().collection("Conversations").addDocument(data: conversation){ err in
if let err = err {
print("Error creating a convo: \(err)")
} else {
print("Conversation created with ID: \(ref!.documentID)")
StateMachine().action(a: .seekingStarted(ref!.documentID))
}
print("Conversation Creation finished")
}
let documentID = ref?.documentID
print(ref.debugDescription)
}
I'm not sure how to approach this issue, any ideas?
Edit: Okay, the issue is not limited to this block of code, it looks like Firebase is not communicating with the servers. I've waited for more than 5min for the addDocument to return(with error or success) but that never happened.
I noticed that at the initiation of the App BoringSSL complains a bit but this is not new and I don't have problems with the other Firebase services, they work just fine - reading and creating data with no problems.
Edit2: Apparently I can fetch collections and documents from Firestore, the issue seems to be limited to document/collection creation.

The document creation operation takes a little time, if you place the breakpoint inside the asynchronus completion block you will surely get an error or success.

Related

Firebase connecting with simulator but not in real device iOS

I am developing a app which has the connection with Firebase DB. This is one part of my code,
let ref1 = Database.database().reference()
ref1.child("UserId").child("\(user_id)").setValue(["name": "\(name)"])
And this one is working fine in simulator(updating value in firebase DB), but not in real device. I have tried some solutions from this site, still I can't get the output.
Is anyone there to help me?
This could be because you are not authenticated on your device or any other reasons. In order to debug it, I suggest you to add a completion block for your setValue which is going to be called whenever the write has been committed to the database. If the call was unsuccessful for any reasons, you can get the error object and take a look at the error.
yourRef.setValue(["name": "\(name)"]) { (error, dbRef) in
if (error != nil) {
//catch the error here
print("Data could not be saved.")
} else {
print("Data saved successfully!")
}
}
At last, the issue was the real device's date and time. The date and time was incorrect in my device. So, the connection with firebase DB failed. Now, it's fixed. Thanks for you suggestions!!

iOS: CloudKit perform(query: ) does nothing - closure not executed

I am in process in adding CloudKit to my app to enable iCloud sync. But I ran into problem with my method, that executes query with perform method on private database.
My method worked fine, I then changed a few related methods (just with check if iCloud is available) and suddenly my perform method does nothing. By nothing I mean that nothing in perform(query: ) closure gets executed. I have breakpoint on the first line and others on the next lines but never manage to hit them.
private static func getAppDetailsFromCloud(completion: #escaping (_ appDetails: [CloudAppDetails]?) -> Void) {
var cloudAppDetails = [CloudAppDetails]()
let privateDatabase = CKContainer.default().privateCloudDatabase
let query = CKQuery(recordType: APPID_Type, predicate: NSPredicate(format: "TRUEPREDICATE"))
privateDatabase.perform(query, inZoneWith: nil) { (records, error) in
if let error = error {
print(error)
completion(nil)
} else {
if let records = records {
for record in records {
let appId = record.object(forKey: APPID_ID_Property) as? Int
let isDeleted = record.object(forKey: APPID_ISDELETED_Property) as? Int
if let appId = appId, let isDeleted = isDeleted {
cloudAppDetails.append(CloudAppDetails(id: appId, isDeleted: isDeleted == 1))
}
}
completion(cloudAppDetails)
return
}
}
completion(nil)
}
}
My problem starts at privateDatabase.perform line, after that no breakpoints are hit and my execution moves to function which called this one getAppDetailsFromCloud. There is no error...
This is my first time implementing CloudKit and I have no idea why nothing happens in the closure above.
Thanks for help.
EDIT: Forgot to mention that this metod used to work fine and I was able to get records from iCloud. I have not made any edits to it and now it does not work as described :/
EDIT 2: When I run the app without debugger attached then everything works flawlessly. I can sync all data between devices as expected. When I try to debug the code, then I once again get no records from iCloud.
In the completion handler shown here, if there's no error and no results are found, execution will fall through and quietly exit. So, there are two possible conditions happening here: the query isn't running or the query isn't finding any results. I'd perform the following investigative steps, in order:
Check your .entitlements file for the key com.apple.dev.icloud-container-environment. If this key isn't present, then builds from xcode will utilize the development environment. If this key is set, then builds from xcode will access the environment pointed to by this key. (Users that installed this app from Testflight or the app store will always use the production environment).
Open the cloudkit dashboard in the web browser and validate that the records you expect are indeed present in the environment indicated by step 1 and the container you expect. If the records aren't there, then you've found your problem.
If the records appear as expected in the dashboard, then place the breakpoint on the .perform line. If the query is not being called when you expected, then you need to look earlier in the call stack... who was expected to call this function?
If the .perform is being called as expected, then add an else to the if let record statement. Put a breakpoint in the else block. If that fires, then the query ran but found no records.
If, after the above steps, you find that the completion handler absolutely isn't executed, this suggests a malformed query. Try running the query by hand using the cloudkit dashboard and observing the results.
The closure executes asynchronously and usually you need to wait few seconds.
Take into account you can't debug many threads in same way as single. Bcs debugger will not hit breakpoint in closure while you staying in your main thread.
2019, I encountered this issue while working on my CloudKit tasks. Thunk's selected answer didn't help me, so I guess I'm gonna share here my magic. I got the idea of removing the breakpoints and print the results instead. And it worked. But I still need to use breakpoints inside the closure. Well, what I had to do is restart the Xcode. You know the drill in iOS development, if something's not right, restart the Xcode, reconnect the device, and whatnot.

iOS: trying to access Firestore triggers EXC_BAD_ACCESS

Swift 4 project in Xcode 9.2
I'm trying to use Firestore in a project. I've added the libraries and cut and pasted the sample code from the FireStore intro guide. But I'm getting an EXC_BAD_ACCESS and have not been able to figure out why. Here's the code I'm trying to run:
let db = Firestore.firestore()
var ref: DocumentReference? = nil
ref = db.collection("users").addDocument(data: [
"first": "Ada",
"last": "Lovelace",
"born": 1815
]) { err in
if let err = err {
print("Error adding document: \(err)")
} else {
print("Document added with ID: \(ref!.documentID)")
}
}
And here's a screen dump of the error:
ANyone have an idea as to what's going wrong?
Same problem over here. Everything used to work fine untill the last iOS SDK update. If I write data to firestore they are not shown in console, sometimes after a few minutes or a hour.
App crashes on this message every few minutes:
2018-01-09 10:10:17.284630+0100 spontRestaurantAppIos[18971:19308343] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FIRESTORE INTERNAL ASSERTION FAILED: closeWithFinalState should only be called for a started stream that has an active delegate.'
I've contacted firestore support and this is what I got back:
Upon checking, this a known bug with our iOS SDK. This is now on our radar and our engineers are currently on it.
For any updates, please watch out on our release notes.
So I guess we'll just have to wait... anybody have other suggestions?
Also see this issue in github:
https://github.com/firebase/firebase-ios-sdk/issues/596
In my case, I don't get a error for 4 minutes. Then it crashes with
2018-01-09 21:11:23.584982+1100 Crux[2671:334948] *** Assertion failure in -[FSTWriteStream closeWithFinalState:error:], third_party/firebase/ios/Source/Firestore/Source/Remote/FSTStream.m:348
Still no idea why.
I just figured out that the error was due to the database rules not allowing access. I opened up the rules to allow public read write and it's now working.

NSUncaughtExceptionHandler when using Realm with Crashlytics

I've got Fabric installed in my app, with Crashlytics enabled via a simple Fabric.with([Crashlytics.self]) call in AppDelegate. Everything was working great, until I pulled in Realm. I have a dead-simple function;
class func listObjects() {
let realm = try? Realm()
if let realm = realm {
let objSet = realm.objects(TestObject.self)
print("Retrieved \(objSet.count) objects")
}
}
Calling the function actually works just fine, but I get an odd warning;
[Crashlytics:Crash] Warning: NSUncaughtExceptionHandler is '_ZZ34RLMInstallUncaughtExceptionHandlervEN3$_08__invokeEP11NSException' in '<...>/Frameworks/Realm.framework/Realm'
Has anyone come across this before?
I guess this is happening because Crashlytics checks whether the uncaught exception handler is overridden, because it is relying on that itself, but it is commonly misused for purposes where there would be less dangerous solutions. 🐉
Realm is using this for good reasons: we need to tear down open write transactions. While we are doing that, we still ensure to call the previously configured exception handler as you can see here. So Crashlytics won't loose it's ability to report any exceptions in your app.

CloudKit method call hung up

When app starts some preliminary process take place. Sometimes it is done quickly in some second, and sometimes It does not end, but without any error it hung up.
I.e. at launch client always fetch the last serverChangedToken. and sometimes it just hung up it does not complete. I am talking about production environment, developer works well. So this route get called, but some times it does not finishes. Any idea why? I do not get any error, timeout.
let fnco = CKFetchNotificationChangesOperation(previousServerChangeToken: nil)
fnco.fetchNotificationChangesCompletionBlock = {newServerChangeToken, error in
if error == nil {
serverChangeToken = newServerChangeToken
dispatch_sync(dispatch_get_main_queue(), {
(colorCodesInUtility.subviews[10] ).hidden = false
})
} else {
Utility.writeMessageToLog("error 4559: \(error!.localizedDescription)")
}
dispatch_semaphore_signal(sema)
}
defaultContainer.addOperation(fnco)
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
I know it is not recommended to use semaphores to control flow of the CloudKit method calls.
Do you think the last two line can be swapped? First dispatch_semaphore_wait and then addOperation be called?
Strange that app worked for iOS 8, this bug arise only in iOS 9.
Adding the following line of code will probably solve your problem:
queryOperation.qualityOfService = .UserInteractive
In iOS 9 Apple changed the behavior of that setting. Especially when using cellular data you could get the behaviour you described.
The documentation states for the .qualityOfService this:
The default value of this property is NSOperationQualityOfServiceBackground and you should leave that value in place whenever possible.
In my opinion this is more a CloudKit bug than a changed feature. More people have the same issue. I did already report it at https://bugreport.apple.com

Resources