NSDictionary has value of none - ios

I want the user to add Friends. However whenever I click on addFriend button I get a breakpoint with an thread 1. There is no further error information rather than 11db.
I have found out by now that the NSDictionary of "otherUser" has the value of none. Thats the reason everything is not working. However I have no clue why that is. Out of the same NSDictionary , I get the username and the profile Pic. Why is it nil then?
var otherUser: NSDictionary?
override func viewDidLoad() {
super.viewDidLoad()
databaseRef.child("user").child(self.otherUser?["uid"] as! String).observe(.value, with: { (snapshot) in
let uid = self.otherUser?["uid"] as! String
self.otherUser = snapshot.value as? NSDictionary
self.otherUser?.setValue(uid, forKey: "uid")
}) { (error) in
print(error.localizedDescription)
}
}
#IBAction func addFriend(_ sender: Any) {
if self.befreunden.titleLabel?.text == "Als Freund hinzufügen" {
let friendRef = "befreundet/\(self.loggedinUSerData?["uid"] as! String)/\(self.otherUser?["uid"] as! String)"
let BefreundenData = ["username":self.otherUser?["username"] as? String,
"ProfilePic":self.otherUser?["urltoImage"] as! String!]
let childUpdats = [friendRef:BefreundenData]
databaseRef.updateChildValues(childUpdats)
}else {
FreundeAnzahl = self.otherUser?["AnzahlFreunde"] as! Int + 1
}
}
Edit:
I've just found out, that the NSDictionary of otherUser has all the values needed inside the viewdidLoad. But as soon as I call the uid of the otherUser in the addFriend function it gives back a value of nil.
Why is it happening?

I fixed the issue by simple giving the uid of the otheruser NSDictionary to a new variable which I created in the viewdidLoad.
This way I do not face any issues regarding unwrapping optionals later on.

Related

Ambiguous use of 'subscript' despide the same code working elsewhere?

I have code which retrieves users from firebase. The problem is that I get the error:
Ambiguous use of 'subscript'
On the lines, I marked in the block below. The weird thing is that the exact same code is currently in another project in nearly identical circumstances and it does not get this error.
The code is below:
func retriveUsers() {
let ref = Database.database().reference()
ref.child("user2").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
let users = snapshot.value as! [String : AnyObject]
self.users.removeAll()
for (_, value) in users {
if let uid = value["uid"] as? String {//Error
if uid != Auth.auth().currentUser?.uid {
let userToShow = User()
if let fullName = value["full name"] as? String {//Error
userToShow.fullName = fullName
userToShow.userID = uid
self.users.append(userToShow)
}
}
}
}
})
print(users.count, " This is the number of users retrived the first looks like: ", users[0].userID)
}
I have looked here and here and neiother has solved my problem. What is the solution here?
The compiler doesn't know the type of value in users, you provided AnyObject which is ambiguous because it can be both an array (index subscripted) or dictionary (key subscripted).
Be more specific and tell the compiler that value is a dictionary, by the way it's always supposed to be Any not AnyObject and check the type safely
if let users = snapshot.value as? [String : [String:Any]] { ...

After adding a row of data to firebase on reload through IOS, data missing

In IOS, I navigate to a screen and add data via the following code:
let dbRow = FIRDatabase.database().reference().child("bikes").child(self.userUid).childByAutoId()
dbRow.child("brand").setValue(self.brand.text)
dbRow.child("model").setValue(self.model.text)
dbRow.child("year").setValue(self.year.text)
dbRow.child("serialNo").setValue(self.serialNo.text)
dbRow.child("store").setValue(self.store.text)
dbRow.child("imageURL").setValue(metadata?.downloadURL()!.absoluteString)
self.navigationController!.popViewController(animated: true)
after I navigate back and in the ViewDidLoad function of the originating screen, I have the following code:
FIRDatabase.database().reference().child("bikes").child(userUid).observe(FIRDataEventType.childAdded, with: { (snapshot) in
if snapshot.exists() {
let bike = Bike()
bike.bikeKey = snapshot.key
let bikeDict = snapshot.value as! [String : AnyObject]
bike.brand = bikeDict["brand"] as! String
bike.ImageUrl = bikeDict["imageURL"] as! String
bike.model = bikeDict["model"] as! String
bike.SerialNo = bikeDict["serialNo"] as! String
bike.Store = bikeDict["store"] as! String
bike.year = bikeDict["year"] as! String
self.bikes.append(bike)
self.tableView.reloadData()
}
// print(self.bikes.count)
// method to get current user id FIRAuth.auth()!.currentUser!.uid
})
getting the brand works, but the access to imageURL, returns an error EXC_BAD_INSTRUCTION. However, on the first time loading the screen all of the rows are returned. Any thoughts?
You should reload the data asynchronously. I'm on the phone now and am not sure if this code will work, but you can give it a try:
DispatchQueue.main.async {
self.tableView.reloadData()
}

Read values from database into Array

I'm trying to read from the database and place the values into an array of strings. However, when I try to push the values into an array then print the array the app crashes.
var pets: [String]?
override func viewDidLoad() {
super.viewDidLoad()
let userRef = FIRDatabase.database().reference().child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("pets")
userRef.observeSingleEvent(of: .value, with: { snapshot in
if let snap = snapshot.value as? Bool {
print("no values")
} else if let snap = snapshot.value as? NSDictionary {
for value in snap {
print(value.key as! String) // Prints out data in the database
self.pets?.append(value.key as! String)
}
print(self.pets!)
}
})
Does anybody know why the print(value.key as! String) prints out the data but then when I print out the array the app crashes with unexpectedly found nil while unwrapping an Optional value?
You never initialize pets. You declare it as an optional but never assign it a value. Why not change your code to the following:
var pets = [String]() // start with an empty array
override func viewDidLoad() {
super.viewDidLoad()
let userRef = FIRDatabase.database().reference().child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("pets")
userRef.observeSingleEvent(of: .value, with: { snapshot in
if let snap = snapshot.value as? Bool {
print("no values")
} else if let snap = snapshot.value as? NSDictionary {
for value in snap {
print(value.key as! String) // Prints out data in the database
self.pets.append(value.key as! String)
}
print(self.pets)
}
})
Your array is nil when you try to force-unwrapping using:
print(self.pets!)
As you are using self.pets?.append() you don't have any problem because you are using the chaining of optionals, but your array, in fact, is nil at that time because you forgot to initialize it before use it. If you instead use self.pets!.append() you will see a runtime error instead.
So as #rmaddy suggest you can initialize the array at the beginning or just inside your viewDidLoad() it's up to you.
I hope this help you.

Getting the values of data stored in firebase

I'm trying to get access to the values stored in firebase dashboard to use them in different functions and methods in the class.
I used this method in this question
I have tried to print their values, the whole app has crashed and it gave me that their nil!
They are not nil actually!
I used a similar method in viewDidLoad and I could retrieve the values to labels!
let refer = FIRDatabase.database().reference().child("UserDevices")
var globalEmail : String!
var globalPhone : String!
var globalImageUrl: String!
override func viewWillAppear(_ animated : Bool){
super.viewWillAppear(animated)
retrieveUserData{(email,phone,ImageUrl) in
self.globalEmail = email
self.globalPhone = phone
self.globalImageUrl = ImageUrl
}
}
func retrieveUserData(_ completionBlock : #escaping ((_ email : String?, _ phone : String?, _ ImageUrl: String?)->Void)){
refer.child(byAppendingPath: self.strUserid as String).observe(.value , with: {snapshot in
if let userDict = snapshot.value as? [String:AnyObject] {
completionBlock(userDict["email"] as! String, userDict["phone"] as! String, userDict["ImageUrl"] as! String)
}
})
}
var strUserid : NSString!
override func viewDidLoad() {
super.viewDidLoad()
print(globalEmail)
print(globalImageUrl)
print(globalPhone)
self.navigationController?.navigationBar.tintColor = UIColor.white
print("idis \(self.strUserid)")
let ref = FIRDatabase.database().reference().child("UserDevices")
self.navigationController?.navigationBar.tintColor = UIColor.white
ref.child(byAppendingPath: self.strUserid as String).observe(.value, with: { snapshot in
if let dict = snapshot.value as? NSMutableDictionary{
print("dict is \(dict)")
if let Provider = dict["name"] as? String
{
self.DeviceDetailsProvider.text = Provider
// self.navigationItem.title = Provider
}
if let name = dict["DeviceName"] as? String
{
self.DeviceDetailsName.text = name
self.navigationItem.title = name
}
if let ShortDescription = dict["Description"] as? String
{
self.DeviceDetailsDescription.text = ShortDescription
}
if let City = dict["city"] as? String
{
self.DeviceDetailsCity.text = City
}
}
})
self.DeviceDetailsImageView.downloadedFrom(link: globalImageUrl)
}
Why I'm getting a crash here!
Change ref.child(byAppendingPath: self.strUserid as String)
To:-
ref.child(self.strUserid)
Also remove let refer = FIRDatabase.database().reference().child("UserDevices").
You can not initialise your reference globally outside a scope because you don't know in which order your classes are being initialised, and probable scenario is that your FIRDatabase hasn't even been initialised yet when you try to initialise let refer.
Instead of refer in retrieveUserData use
FIRDatabase.database().reference().child("UserDevices")
You see in a viewController's LIFE CYCLE, viewdidLoad is called before than viewWillAppear:
So what you need is:-
override func viewDidLoad() {
super.viewDidLoad()
..
retrieveUserData{(email,phone,ImageUrl) in
self.globalEmail = email
self.globalPhone = phone
self.globalImageUrl = ImageUrl
self.DeviceDetailsImageView.downloadedFrom(link: globalImageUrl)
// .. Do your stuff...
}
}
Read: Viewcontroller's Lifecycle

Array keeps returning nil even when values are stored Swift Firebase

Hi I am new to Swift and Firebase here and I am trying to append the objects I get into the array I have created. But when I return the array, it returns nil even when I print the array it shows the values are stored inside.I tried to assign it to another array but it still returns nil. Please help me as I am currently a newbie to Swift and Firebase and need some guidance. Thanks in advance.
func retrieveData() -> Array<AnyObject>{
var ref = Firebase(url: "my_firebase_url")
ref.queryOrderedByChild("datetime").observeEventType(.Value, withBlock: {
snapshot in
if let i = snapshot.value as? NSDictionary {
for item in i {
if let value = item.value as? NSDictionary {
self.adArray.append(value)
println(self.adArray[0])
println(self.adArray.count)
self.codeNum = value["code"] as! String
self.datetime = value["datetime"] as! String
self.nameEvent = value["name"] as! String
println("code is \(self.codeNum) and name is \(self.nameEvent) at \(self.datetime)")
}
}
}
})
println(adArray.count)
return adArray }

Resources