Firestore 'Document path cannot be empty.' - swift

First of all, in general, there is not much information regarding this error, and those that are do not solve the problem.
When registering \ logging in via Apple Sign In, a collection of users is created, for some reason the name is not displayed after logging in to your personal space, but this is not even the problem (I hope), there is a function to change the name in the settings, but after confirming the app crashes with error:
terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'FIRInvalidArgumentException', reason: 'Document path cannot be empty.'
From this thread:
iOS Firestore 'Document path cannot be empty'
I understood this:
Some people would get a similar issue because in an older version of Firebase, the check statements for document would only check for a nil string rather than an empty. The latests versions of Firebase check for nil and an empty string.
But no matter what Im do I still get this error.
static func updateUserName(with newName: String, uid: String, completion: #escaping (Result<Bool, Error>) -> Void) {
let reference = Firestore.firestore().collection(FBKeys.CollectionPath.users)
.document(uid)
reference.setData(["name": newName], merge: true) { err in
if let err = err {
completion(.failure(err))
return
}
completion(.success(true))
}
}
So, in general, the question is clear, what exactly needs to be done with .document(uid)?

Related

It works sometimes, but some throws error: Generic parameter 'T' could not be inferred - Swift

Until now I had no problems, which is the weird part. Swift never complained about this code. A user got an error signing up and me debugging put a print statement and maybe because of the introspection of the code now swift caught the error and is saying:
Generic parameter 'T' could not be inferred
I thought this is how you handle continuation, what's wrong in my code?
The funny thing is that it works sometimes, others it throws the error above :/
The error is in line: try await withCheckedThrowingContinuation
Here's the full code:
// Signup
final func signUp(username: String, email: String, password: String) async throws -> (message: String, didItSucceed: Bool) {
print("➡️ About to sign up user")
try await withCheckedThrowingContinuation { continuation in
let userAttributes = [AuthUserAttribute(.email, value: email)]
let options = AuthSignUpRequest.Options(userAttributes: userAttributes)
_ = Amplify.Auth.signUp(
username: username,
password: password,
options: options
) { result in
switch result {
case .success(let signUpResult):
print("✅ Signup confirmed. Next-> needs email verification from \(email)")
switch signUpResult.nextStep {
case .done:
print("✅ Finished sign up!")
case .confirmUser(_, _):
DispatchQueue.main.async {
// Confirm the Auth State to confirm code passing in the username to confirm
self.authState = .login
}
continuation.resume(returning: ("Check your Email 📧", true))
}
case .failure(let error):
var errorMessageToTheUser = "Something went wrong 🤔"
print(error)
continuation.resume(returning: (errorMessageToTheUser, false))
}
}
}
}
EDIT:
If I remove the print() on top of the withCheckedThrowingContinuation the exception goes away. But the error when user signs up still remains and it crashes at line:
try await withCheckedThrowingContinuation { continuation in
and takes (the error) to the #main struct saying: Thread 1: EXC_BAD_ACCESS (code=1, address=0x46b56a8a6b20)
What's wrong?
First of all, you should be using withUnsafeThrowingContinuation. The Checked version is just for testing that you are doing everything correctly; it has overhead that you don't want to encounter unless you have to. (However, as we shall see, you are not doing everything correctly, so this was actually a good choice for the moment!)
Second, if you look at the docs, you will see that this is a generic function, whose type T is resolved through the resolution of the CheckedContinuation (your continuation). So instead of merely saying
continuation in
you can, if necessary, supply the type information:
(continuation: CheckedContinuation<WhatType, Error>) -> Void in
(I do not know what type you should put for WhatType because you have not given enough information.)
Third, you are crashing because you are using the continuation incorrectly. You must call continuation.resume exactly once on every possible path of exit within your implementation, and you are not doing that (look at the .done path for example). I think you will find that when you get this worked out, the other problems will just go away.
Fourth, the reason why the print statement changed everything is that before you put that there, there was an implicit return before your try await. Thanks to that, the compiler was able to infer the types in question. But you took that away when you added the print. If you put return try await your compilation problems might all go away (though you will still crash because you are not using the continuation properly).

Getting NSInvalidArgumentException when posting a Dictionary to Firestore

I'm trying to add an array of custom objects to a Firestore Database. The Dictionary looks as follows:
for (n, eventInArray) in currentEvents.enumerated() {
ref.updateData(["Events":
[n:
["activity": eventInArray.activity],
["dateAndTime"]: ["date": eventInArray.dateAndTime.date,
"time": eventInArray.dateAndTime.time],
"name": eventInArray.name
]])}
But when running the app and sending the data, I get following error message:
NSInvalidArgumentException', reason: '-[__NSCFNumber getBytes:maxLength:usedLength:encoding:options:range:remainingRange:]: unrecognized selector sent to instance 0xd628e63903198e1c'
I figured out a way to work around this issue.
Instead of updating one field, I updated the whole document using a do - catch block:
do {
try ref.setData(from: groupDataForDb)
} catch let error {
print("Error writing to firestore \(error)")
}
The groupDataForDb variable is a struct that conforms to Codable, and has properties matching the fields in the Firestore Document.

eventStore.saveCalendar returns an error "json error: An unexpected error occurred."

I am trying to implement the same code in https://www.andrewcbancroft.com/2015/06/17/creating-calendars-with-event-kit-and-swift/, but I get an error stating "json error: An unexpected error occurred." I am developing this project for macOS.
This is my following code,
#IBAction func addPressed(_ sender: NSButton) {
// Create an Event Store instance
let eventStore = EKEventStore();
// Use Event Store to create a new calendar instance
// Configure its title
let newCalendar = EKCalendar(for: .event, eventStore: eventStore)
// Probably want to prevent someone from saving a calendar
// if they don't type in a name...
newCalendar.title = "DCU"
// Access list of available sources from the Event Store
let sourcesInEventStore = eventStore.sources
// Filter the available sources and select the "Local" source to assign to the new calendar's
// source property
newCalendar.source = sourcesInEventStore.filter{
(source: EKSource) -> Bool in
source.sourceType.rawValue == EKSourceType.local.rawValue
}.first!
// Save the calendar using the Event Store instance
do {
try eventStore.saveCalendar(newCalendar, commit: true)
} catch {
print("json error: \(error.localizedDescription)")
}
}
When I build the project and click run it gives me the error "json error: An unexpected error occurred.". When I try to add an event to defaultcalendar it gives me an error "json error: No calendar was set". I have tried all the available sources online but couldn't find a solution. Somehow neither eventStore.save or eventStore.saveCalendar is working for me. Can someone please let me know where might I be going wrong?
Two possible reasons
From the documentation of EKEventStore
To access the user’s Calendar data, all sandboxed macOS apps must include the com.apple.security.personal-information.calendars entitlement. To learn more about entitlements related to App Sandbox, see Enabling App Sandbox.
Check the authorizationStatus of the store and call requestAccess if necessary.
Your error message is misleading, the error has nothing to do with JSON.

SecTransformExecute() crashes the app with EXEC_BAD_ACCESS

I have a private/public key pair and I'm trying to encrypt a String with either of them. The code is running on OSX 10.11 and Xcode 7.2
func encryptMessageWithKey(message: String, keyType: KeyType,
withCompletionBlock: (success: Bool, data: NSData?, error: AsymCryptoExceptions.Exceptions?)
-> Void) {
let uintData = [UInt8](message.utf8)
let sourceData = CFDataCreate(kCFAllocatorDefault, uintData, uintData.count)
let privKey = self.getPrivateKeyReference()!
var errorRef: Unmanaged<CFError>?
let encoder = SecEncryptTransformCreate(privKey, &errorRef)
SecTransformSetAttribute(encoder,
kSecPaddingKey,
kSecPaddingPKCS1Key,
&errorRef)
SecTransformSetAttribute(encoder,
kSecTransformInputAttributeName,
sourceData,
&errorRef)
var encryptedData = SecTransformExecute(encoder, &errorRef)
if (errorRef != nil) {
let error = errorRef!.takeRetainedValue()
print(error)
}
}
The above is failing miserably, causing the app to crash at runtime with EXEC_BAD_ACCESS. No errors, nothing.
My research has shown that there might be a bug related to explicitly specifying kSecPaddingPKCS1Key as opposed to NULL which will set the padding to PKCS1 by default. However, I wasn't able to set this value to NULL since Swift has replaced that with nil and that can't be used in this spot.
Even though this is a pretty old question, I will answer it to maybe save someone else some time :)
I had the same problem where SecTransformExecute gave an EXC_BAD_ACCESS error. I noticed that the error would only occur when I changed or cleaned the project and rebuilt the app, but not when I would run the same debug build.
In the end, signing the application with a development certificate is what solved it for me, since before the app could not use the key due to the different automatic signing identities provided by Xcode.

NSURLSession crashing from Swift

I've got a simple class that uses an NSURLSession.
class test {
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration());
func f() {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0), { () -> Void in
var task = self.session.dataTaskWithRequest(request, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if error != nil {
// cry
return;
}
var error: NSError? = nil;
var dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as! Dictionary<String, String>;
// use dict
});
task.resume();
});
}
When I try to deserialize the data as JSON, the application crashes.
I've determined that the data seems to be of the right length but the content looks like garbage in the debugger, so it seems to me that the data object passed in is broken. Furthermore, I suspect some stack smashing as I can step through this completion handler and see that it's the attempt to deserialize the data that's crashing, but when the actual crash occurs, the stack in the debugger mentions nothing about the completion handler or any of my code.
I've seen several samples of using NSURLSession that look pretty much exactly like mine that just work. I tried using the shared session instead of making a new one, but that did not help either.
What is causing this crash?
Seems that the JSON was not actually all strings- I brainfarted and one of them was actually a number.
The real problem in the question is that Swift is completely worthless when handling the problem of force casts failing. Not only do you not get any kind of useful error at runtime that you could handle or recover from, but the debugging information presented when it occurs is completely misleading and points to totally the wrong place. You simply get a trap in a function without symbols with the wrong callstack.