Key value pair not getting added to my dictionary in Swift - swift

I am trying to add an item to my dictionary. profileURL contains the correct value as I have seen from what the print statement gives me but for some reason the dictionary is not creating a new entry with it. Any solutions?
Here is my code:
storageRef.downloadURL(completion: {(url, error) in
if error != nil {
return
}
if let profileURL = url?.absoluteString {
print("SHOULD BE DATA HERE: ", profileURL)
databaseValues["profileUrl"] = profileURL
}
})

Related

How can I add these Firestore fields to a Dictionary?

I am looking to add all my "usernames" into a dictionary. I am having some trouble doing this. I am sure it's very obvious, but I am very new to coding.
I am stuck at, right now and can't seem to find a clear answer anywhere:
func fetchUser() {
let db = Firestore.firestore()
let usernameSearch = db.collection("users")
usernameSearch.getDocuments { (snapshot, error) in
if error != nil {
print("Error obtaining usernames")
} else {
for field in snapshot!.documents {
let field = field.get("username")
print(field!)
}
}
}
}
I would really appreciate it if somebody could help me out. I am sure it's very obvious, or I'm just doing it totally wrong.
First, get into the habit of safely unwrapping over force unwrapping. And choose more accurate names for your objects (i.e. usersCollection over usernameSearch). However, in this case, there's no need to instantiate individual properties for the database and the collection since they're not being used anywhere else but here (so be efficient and omit them).
var usersDictionary = [String: [String]]()
func fetchUser() {
Firestore.firestore().collection("users").getDocuments { (snapshot, error) in
if let snapshot = snapshot { // unwrap the snapshot safely
var usernames = [String]()
for doc in snapshot.documents {
if let username = doc.get("username") as? String {
usernames.append(username)
}
}
usersDictionary["usernames"] = usernames
} else {
if let error = error {
print(error)
}
}
}
}
Or if you actually meant an array of users:
var usersArray = [String]()
func fetchUser() {
Firestore.firestore().collection("users").getDocuments { (snapshot, error) in
if let snapshot = snapshot { // don't force unwrap with !
for doc in snapshot.documents {
if let username = doc.get("username") as? String {
usersArray.append(username)
}
}
} else {
if let error = error {
print(error)
}
}
}
}
I'm assuming that what you're looking for is an Array, not a Dictionary. I'll also assume that you are indeed getting the correct value that you'd expect out of field.get("username"), e.g. a string such as "Bob." Therefore, what you are trying to do is map the list of document objects to a list of strings.
If you scroll to the Topics section of the Array documentation from Apple, you can find some of the operations they provide for arrays such as snapshot!.documents.
One of those operations is actually map, and its description is:
Returns an array containing the results of mapping the given closure over the sequence’s elements.
https://developer.apple.com/documentation/swift/array/3017522-map
In other words, you provide a transformation to perform for each instance of a document belonging to the snapshot!.documents Array and get back a new Array containing the resultant values of that transformation.
In this case I will use a more specific operation; compactMap. We have to try and cast the returned value from Any to String. If that does not succeed, it will return nil, and we'll want to filter that out. I expect it to be an unlikely case due to the type requirements made by the Firebase Console, but it's good to be aware of it. Here is the example:
func fetchUsernames(from usernameCollection: String, completion: #escaping ([String]) -> Void) {
let db = Firestore.firestore()
let collection = db.collection(usernameCollection)
collection.getDocuments { snapshot, error in
guard error != nil,
let usernames = snapshot?.documents.compactMap { $0.get("username") as? String }
else { return print("Error obtaining usernames") }
completion(usernames)
}
}
The key line here being let usernames = snapshot?.documents.compactMap { $0.get("username") }. We are passing the map function a closure. This closure is passed an argument itself; each value from the snapshot?.documents array. You may refer to this passed in value with $0.

Get Data from firebase for swift

I have below code to get data from my firebase database
db.collection("users").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
print("starting name display")
for document in (querySnapshot?.documents)! {
let documentUserId = document.get("uid") as?String
let temp = document.data()["displayName"]
print(temp)
}
}
}
The print statement displays as optional("test name")
Why am i keep getting optional in my string. Same displays on the screen as well.
You need to un-wrap because it's an Optional. Means it could have a value or it could not have a value. So this is one method to handle it:
let temp = document.data()["displayName"] ?? ""
print(temp)
You could also use if let or guard let statements if you need to handle the cases where the value is actually empty.
Note: Take a look at the basics of swift. There is a separate section for Optionals.

Cannot assign values from functions to dictionary array Swift 4

I've encountered the following error in two different scenarios that may be related. The error is:
lldb Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
This is the code for the first scenario:
db.collection("properties").getDocuments()
{
(querySnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
for document in querySnapshot!.documents {
var propertyData = [String:[String]]()
let listingType = (document.get("listingType") as! [String])
propertyData["listingType"]![0] = listingType[0]
}
}
}
I am trying to get a list of properties that I have already set in Firestore. I can print the listingType variable to the console and it successfully prints "Sale". However when I assign the variable it then gives that error.
I have experienced the same issue when using the location manager functions. If I get the user's current location coordinates, when I try to add those coordinates to a global dictionary it throws the same error. I am writing the code in Swift 4.
You can't just assign something to [0] since the array is initially nil
if propertyData["listingType"] == nil {
propertyData["listingType"] = [listingType[0]] //Create a new array with the string
} else {
propertyData["listingType"]![0] = listingType[0]
}

Retrieve Data in Parse

I have searched through a number of similar topics but have not found a solution as of yet. I am using Parse social and using the login files.
I get the following error:
"AnyObject?" is not convertible to 'String'
I am very new to Swift & Parse - I believe this is the correct method of retrieving data, so please correct me if I am wrong.
var userObjectID = PFUser.currentUser()!.objectId!
var query = PFQuery(className:"User")
query.getObjectInBackgroundWithId("\(userObjectID)") {
(userInfo: PFObject?, error: NSError?) -> Void in
if error == nil && userInfo != nil {
println(userInfo)
let userScore = userInfo["level"] as! String
} else {
println(error)
}
}
Below is the database on Parse
I think you need to unwrap the PFObject you receive:
let userScore = userInfo!["level"] as! String

What is the best way to do a fetch request in CoreData?

I'm trying to find the most efficient way to do a fetch request against CoreData. Previously I have first checked if an error existed, and if it did not I have checked the array of the returned entity. Is there a quicker way to do this. Is something like this an accepted way to do the request?
let personsRequest = NSFetchRequest(entityName: "Person")
var fetchError : NSError?
//Is it okay to do the fetch request like this? What is more efficient?
if let personResult = managedObjectContext.executeFetchRequest(personRequest, error: &fetchError) as? [Person] {
println("Persons found: \(personResult.count)")
}
else {
println("Request returned no persons.")
if let error = fetchError {
println("Reason: \(error.localizedDescription)")
}
}
Kind Regards,
Fisher
Checking the return value of executeFetchRequest() first is correct.
The return value is nil if the fetch failed, in that case the error
variable will be set, so there is no need to check if let error = fetchError.
Note that the request does not fail if no (matching) object exist.
In that case an empty array is returned.
let personRequest = NSFetchRequest(entityName: "Person")
var fetchError : NSError?
if let personResult = managedObjectContext.executeFetchRequest(personRequest, error: &fetchError) as? [Person] {
if personResult.count == 0 {
println("No person found")
} else {
println("Persons found: \(personResult.count)")
}
} else {
println("fetch failed: \(fetchError!.localizedDescription)")
}