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]] { ...
Related
This question already has an answer here:
How to subscript a dictionary that is stored inside a dictionary in swift?
(1 answer)
Closed 4 months ago.
I have the following code.
func setUserToken(_ user: NSDictionary) {
self.userId = user["user"]["id"] as! String;
I get the error "Value of type Any has no subscripts". What am I doing wrong?
You need to specify your json before parsing it. Try This:
func setUserToken(_ user: NSDictionary) {
guard let userData = user as? NSDictionary else{return}
guard let user = userData["user"] as? String else{return}
self.userid = user["id"] as? String else{return}
}
The type of any lookup from a NSDictionary is Any. You know (or think you know) it is another dictionary, but Swift does not. You must establish the type before you can do the second lookup.
func setUserToken(_ user: NSDictionary) {
if let userDict = user["user"] as? NSDictionary {
// We now know “user” is a valid key and its value
// is another NSDictionary
if let userId = userDict["id"] as? String {
// We now know “id” is a valid key and its
// value is of type String which has been
// assigned to userId. Now assign it to the
// property
self.userId = userId
return
}
}
// If we get here, something went wrong.
// Assign a reasonable default value.
self.userId = “user unknown”
}
You can do it in a single line using optional chaining and the nil coalescing operator:
self.userId = ((user["user"] as? NSDictionary)?["id"] as? String) ?? “user unknown”
Pictures
-pictureID
-- name
-- date
Like
-pictureID
-- userID: true
-- userID: true
likePerUser
-userID
--pictureID: true
--pictureID: true
Users
-userID
-- name
-- lastname
I would like to retrieve all picture that current user has liked.
I did:
ref.child("likePerUser").child(FIRAuth.auth()!.currentUser!.uid).observeSingleEvent(of: .value, with: { (snap) in
for item1 in snap.children{
let firstItem1 = (snap: item1 as! FIRDataSnapshot)
print("key favourites\(firstItem1.key)")
let firstId = firstItem1.key
self.ref.child("pictures").child(firstId).observeSingleEvent(of: .value, with: { (snapshot) in
for item in snapshot.children{
let firstItem = (snapshot: item as! FIRDataSnapshot)
print("key pictures \(firstItem.key)")
let dict = firstItem.value as! [String: Any
let name = dict["name"] as! String
print(name)
}
Even, If it seems that firstId has the right value each time,
I always get an error:
Could not cast value of type '__NSCFBoolean' (0x110dae5b8) to
'NSDictionary' (0x110daf288).
Please help....
I solved doing this:
if let dictionary = snapshot.value as? NSDictionary {
if let name = dictionary["nome"] as? String {
print(name)
}
}
This questions helped me: Swift - Could not cast value of type '__NSCFString' to 'NSDictionary'
Also i didn't need to iterate once more.
let dict = firstItem.value as! [String: Any
Here is where you attempt to cast a value as a dictionary. It's unclear whether the value is a dictionary based upon the model of the database you've shared. But there's a good chance that if you print firstItem.value.debugDescription, you will see that the value it isn't a dictionary object.
I was trying to initialize the values in the User object but from another question it seems like it's not possible to do it there - now, trying to do the same thing in a view controller in viewDidLoad, I'm running into another error:
This is my call to Firebase in viewDidLoad (myUser is a global variable var myUser:User!):
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").childByAutoId()
let userRefHandle: FIRDatabaseHandle?
userRefHandle = userRef.observe(.value, with: { (snapshot) -> Void in
let userData = snapshot.value as! Dictionary<String, AnyObject>
let id = snapshot.key
if (FIRAuth.auth()?.currentUser?.uid) != nil {
if let name = userData["name"] as! String!, name.characters.count > 0 {
let handle = userData["handle"] as! String!
let gender = userData["gender"] as! String!
let profilePicture = userData["profilePicture"] as! String!
let uid = userData["uid"] as! String!
// let rooms = userData["rooms"] as! [[String : AnyObject]]
myUser.uid = uid
myUser.uid = handle
myUser.uid = name
myUser.uid = profilePicture
myUser.uid = gender
// myUser.rooms = rooms
} else {
print("Error! Could not initialize User data from Firebase")
}
}
})
The end goal for this is so that when a user launches the app (already signed up and their info is in Firebase), their info is pulled from the database and set to the User object so the values can be used around the app (name, handle, profilePicture, etc.).
I'm getting the error: Could not cast value of type 'NSNull' (0x106d378c8) to 'NSDictionary' on the let userData = snapshot.value line.
This is what the user's data looks like in Firebase:
"users" : {
"-KgjW9PEvCPVqzn7T5pZ" : {
"gender" : "male",
"handle" : "TestHandle123",
"name" : "Timothy",
"profilePicture" : "https://graph.facebook.com/*removed*/picture?type=large&return_ssl_resources=1",
"uid" : "2q4VCKu1e7hiL84ObdzgQcQ0pH63"
}
}
I'm wondering if this is the correct way to set a user's values from Firebase, and if so, how to avoid the error?
in your code, you are looking for the profile picture using profile
let profilePicture = userData["profile"] as! String!
but in the data, you have profilePicture
Because you have forced the unwrap you will get this error when the key is not found.
You should make sure that you use the same key in both places. It might also be worth including defaults in case you ever have data issues
let profilePicture = userData["profile"] as? String ?? "default"
Since the user is already signed up you should store the key that references to the firebase user (e.g. via NSUserDefaults). In this case "-KgjW9PEvCPVqzn7T5pZ". Use this in the userRef instead of childByAutoId, which would generate a new child location with a new key and doesn't exists yet (hence the NSNull).
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child("-KgjW9PEvCPVqzn7T5pZ")
I'm a newbie to coding and Swift.
I'm trying to retrieve the value of house1Colour from my Firebase database in my app. I've tried these methods so far.
let eg = FIRDatabase.database().reference(withPath: "test")
(when I use this I get a THREAD 1 Signal SIGABRT error, I'm not sure why)
and:
var test:String!
FIRDatabase.database().reference().child("house1Colour").observeSingleEvent(of: .value, with: {(snap) in
if let snapDict = snap.value as? Dictionary <String, AnyObject>{
self.test = snapDict["house1Colour"] as! String
print(self.test)
}
})
None of them work.
The value of FIRDatabase.database().reference().child("house1Colour") is just the string since you already specified the key house1Colour.
Therefore you should be able to just:
if let snapString = snap.value as? String {
print(snapString)
}
When listening to a new object in Firebase, I get this error: Could not cast value of type NSTaggedPointerString to NSDictionary. Here is the code that listens to a a user that has registered.
FIRAuth.auth()!.addStateDidChangeListener { auth, user in
guard let user = user else { return }
self.user = User(authData: user)
let userref = FIRDatabase.database().reference(withPath: "users").child(self.user.uid)
userref.observe(.value, with: { snapshot in
print(snapshot.value!)
var newItems: [UserItem] = []
for item in snapshot.children {
let userDetail = UserItem(snapshot: item as! FIRDataSnapshot) /////////// CRASHES HERE //////////
newItems.append(userDetail)
}
self.userItem = newItems
})
print(self.user.uid)
}
And when the error comes up it points to here:
init(snapshot: FIRDataSnapshot) {
key = snapshot.key
let snapshotValue = snapshot.value as! [String:Any] ///// ERROR HERE
name = snapshotValue["name"] as! String
email = snapshotValue["email"] as! String
age = snapshotValue["age"] as! String
ref = snapshot.ref
}
The console is printing what is inside Firebase correctly and the data is there and it exists, but this casting or data read error keeps happening. It has something to do with the conversion but I'm not exactly sure.
Say
snapshot.value as! String
In this case, the value is a string, so that is what you must cast to.
it might be the case that you updated your database and the old data did not have the correct format, try deleting your database, add new data and run your program again