I had it working on previous Swift versions like this:
let dictionary = responseObject as! NSDictionary
let result = dictionary.objectForKey("result")!
let geometry = result.objectForKey("geometry")!
let location = geometry.objectForKey("location")!
let lat: Double = location.objectForKey("lat")!.doubleValue
As I understand, there is no doubleValue anymore, so I replaced it like this:
let dictionary = responseObject as! NSDictionary
let result: AnyObject = dictionary.object(forKey: "result") as AnyObject!
let geometry: AnyObject = result.object(forKey: "geometry") as AnyObject!
let location: AnyObject = geometry.object(forKey: "location") as AnyObject!
let lat: Double = location.double(forKey: "lat")
And it crashes:
-[__NSCFDictionary doubleForKey:]: unrecognized selector sent to instance 0x1584aba10
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary doubleForKey:]: unrecognized selector sent to instance 0x1584aba10'
You just need to cast it from Any to [String: Any] or to another type you need to get from it:
let dictionary = responseObject as? [String: Any] ?? [:]
let result = dictionary["result"] as? [String: Any] ?? [:]
let location = result["location"] as? [String: Any] ?? [:]
let lat = location["lat"] as? Double ?? 0
Related
I have this empty dictionary
let orderArray = ["name":"","quntity":"","price":""]
and when i download the data from Firebase, i want to get some elements and put them in the dictionary to read it later
Here's my Firebase method:
self.databaseRef.child("Users").child((Auth.auth().currentUser?.uid)!).child("cart").child(self.orderFromKitchen).observe(DataEventType.value, with: { (snapshot) in
//if the reference have some values
if snapshot.childrenCount > 0 {
//clearing the list
self.ordersList.removeAll()
//iterating through all the values
for info in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
//let key = self.kitchensRef.childByAutoId().key
let infoObject = info.value as? [String: AnyObject]
let name = infoObject?["name"]
let Id = infoObject?["ID"]
let img = infoObject?["img"]
let price = infoObject?["price"]
let quantity = infoObject?["quntity"]
self.nameArr.append((name as! String?)!)
self.quaArr.append((quantity as! String?)!)
let info = ordersModel(id: Id as! String?, name: name as! String?, img: img as! String?, price: price as? Int,quantity:quantity as! String?)
//here i want to add name and price to the dictionary
self.orderArray.insert(contentsOf: "\(infoObject?["name"]!)", at: 0)
self.orderArray.insert(contentsOf: "\(infoObject?["price"]!)", at: 2)
self.ordersList.append(info)
}
//reloading the tableview
self.tableView.reloadData()
self.loadingView.isHidden = true
}
Thank you guys i fixed it by this greate extention
extension Dictionary where Value: RangeReplaceableCollection {
public mutating func append(element: Value.Iterator.Element, toValueOfKey key: Key) -> Value? {
var value: Value = self[key] ?? Value()
value.append(element)
self[key] = value
return value
}
}
self.orderArray.append(element: name2 as! String, toValueOfKey: "name")
but i facing new problem with Firebase
like that
2019-04-03 00:56:48.969048+0200 Ml Matba5[1809:376762] *** Terminating app
due to uncaught exception 'InvalidPathValidation', reason:
'(child:) Must be a non-empty string and not contain '.' '#' '$' '[' or ']''
*** First throw call stack:
thank you guys
have a good day
I had recently added new pods to my project and updated the previous ones, this code had all worked before and now I am getting "Ambiguous use of 'subscript'" I have been checking other answers and it seems like the way I have it currently set up is the correct way. I am not sure why all of a sudden these lines of code would get flagged as errors.
databaseRef.child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { (postsSnapshot) in
let posts = postsSnapshot.value as! [String: AnyObject]
for (_, post) in posts {
for (_, postInfo) in post as! [String: AnyObject] {
if let followingID = postInfo["uid"] as? String {
for each in self.following {
if each == followingID {
guard let uid = postInfo["uid"] as! String? else {return}
guard let name = postInfo["businessName"] as! String? else {return}
guard let address = postInfo["businessStreet"] as! String? else {return}
guard let state = postInfo["businessState"] as! String? else {return}
guard let city = postInfo["businessCity"] as! String? else {return}
let data = ["uid":postInfo["uid"] as! String, "businessName":postInfo["businessName"] as! String, "businessStreet":postInfo["businessStreet"] as! String, "businessState":postInfo["businessState"] as! String, "businessCity":postInfo["businessCity"] as! String,"businessZIP":postInfo["businessZIP"] as! String, "businessPhone":postInfo["businessPhone"] as! String, "businessLatitude":postInfo["businessLatitude"] as! String, "businessLongitude":postInfo["businessLongitude"] as! String, "businessWebsite":postInfo["businessWebsite"] as! String, "facebookURL":postInfo["facebookURL"] as! String, "foursquareURL":postInfo["foursquareURL"] as! String, "googleURL":postInfo["googleURL"] as! String, "instagramURL":postInfo["instagramURL"] as! String, "snapchatURL":postInfo["snapchatURL"] as! String, "twitterURL":postInfo["twitterURL"] as! String, "yelpURL":postInfo["yelpURL"] as! String]
The problem is your use of AnyObject. postInfo is being declared as AnyObject but then you attempt to use it like a dictionary, hence the error.
If post is a dictionary of dictionaries, then declare is as such:
Change:
for (_, postInfo) in post as! [String: AnyObject] {
to:
for (_, postInfo) in post as! [String: [String: AnyObject]] {
This will change postInfo to be [String: AnyObject] instead of AnyObject.
I am trying out FCM messaging service. I have setup everything perfecting. When I receive message from FCM I get the following error. I am not sure what is wrong here:
AnyHashable("google.c.a.c_id"): 1586592282379086000, AnyHashable("gcm.message_id"): 0:1515418580276498%f4373656f4373656]
Could not cast value of type '__NSCFString' (0x1b4c70040) to 'NSDictionary' (0x1b4c70b80).
2018-01-08 19:06:21.198548+0530 Ozone[1067:540436] Could not cast value of type '__NSCFString' (0x1b4c70040) to 'NSDictionary' (0x1b4c70b80).
The strange part is I created a seperate Push Notification App and put the same code, it is working there. What could be wrong here?
Here is the piece code: I am getting the error in let d : [String : Any].....line
UNNotificationPresentationOptions) -> Void) {
print("Handle push from foreground\(notification.request.content.userInfo)")
let dict = notification.request.content.userInfo["aps"] as! NSDictionary
let d : [String : Any] = dict["alert"] as! [String : Any]
let body : String = d["body"] as! String
let title : String = d["title"] as! String
print("Title:\(title) + body:\(body)")
self.showAlertAppDelegate(title: title,message:body,buttonTitle:"ok",window:self.window!)
}
Can some one help me with this? I know it is very general error but not sure why this is coming as it is working fine in another app.
Thanks!
alert key can be string or dictionary (depends on your server). You can try this.
if let dict = notification.request.content.userInfo["aps"] as? [String : Any] {
if let d = dict["alert"] as? [String : Any],
let body = d["body"] as? String,
let title = d["title"] as? String {
print("Title:\(title) + body:\(body)")
} else if let body = dict["alert"] as? String {
print("body:\(body)")
}
}
And also you should avoid force casting and don't use NSDictionary in swift.
This is my data structure.
This is how I load club data and its address.
func loadClubs() {
ref = Database.database().reference()
ref.child("club").observe(DataEventType.childAdded, with: { (clubSnapshot) in
if let clubDict = clubSnapshot.value as? [String : AnyObject] {
let name = clubDict["name"] as! String
let explanation = clubDict["explanation"] as! String
let courtNum = clubDict["courtNum"] as! Int
let membershipFee = clubDict["membershipFee"] as! Int
let visitorFee = clubDict["visitorFee"] as! Int
let hasCarParking = clubDict["hasCarParking"] as! Bool
let club2 = Club2(name: name, explanation: explanation, courtNum: courtNum, membershipFee: membershipFee, visitorFee: visitorFee, hasCarParking: hasCarParking)
self.club2Array.append(club2) // Add to clubArray
print(self.club2Array)
self.tableView.reloadData()
}
let addressRef = Database.database().reference()
addressRef.child("address").child(clubSnapshot.key).observe(DataEventType.childAdded, with: { (addressSnapshot) in
if let addressDict = addressSnapshot.value as? [String: AnyObject] {
let clubAddress = ClubAddress(postCode: addressDict["postcode"] as! String, cityName: addressDict["city"] as! String, ward: addressDict["ward"] as! String, address1: addressDict["address1"] as! String, address2: addressDict["address2"] as! String)
self.addressArray.append(clubAddress)
print(self.addressArray)
}
})
})
}
basically, after retrieving each snapshot of club, I get club's key (-KsJB9TkoGNIkiZFGg7), then use that key to retrieve address.
However, print(self.addressArray) doesn't not print anything.
I add a debug breakpoint at if let addressDict = addressSnapshot.value as? [String: AnyObject] { , it does not stop the debug process.
Why is it not calling?
What do I miss here?
Ah! Your code is very close.
Keep in mind that .childAdded iterates over all of the child nodes and loads each one.
In your case, you don't want to iterate over all of the address nodes, you just want one, and don't want to leave an observer.
To do that, we load the specific node child data of the address node, by observeSingleEvent(of: .value. Here's a snippet of the important part.
let addressRef = Database.database().reference()
addressRef.child("address").child(clubSnapshot.key)
.observeSingleEvent(of: .value, with: { (addressSnapshot) in
let dict = addressSnapshot.value as! [String: Any]
let address = dict["address1"] as! String
print(address)
Here is the code:
func observeMessages() {
let ref = FIRDatabase.database().reference().child("messages")
ref.observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let message = Message()
message.setValuesForKeys(dictionary)
self.messages.append(message)
//this will crash because of background thread, so lets call this on dispatch_async main thread
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
When run, it crashes like this:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name.'
Please kindly help me fix this.
The problem is that there is a mismatch between your Message model class and what you are trying to put inside of your instance of it through the setValuesForKeys method. Your dictionary does not line up with the Message class.
This is what the error message tells you: your app tried to set a value for a key from your snapshot.value that does not exist in your Message class.
Check that there is exactly the same number of properties with the same name in your Message class as in your snapshot.value.
To avoid mismatches, you could define your Message class as such:
class Message: NSObject {
var fromId: String?
var text: String?
var timestamp: NSNumber?
var toId: String?
var imageUrl: String?
var imageWidth: NSNumber?
var imageHeight: NSNumber?
init(dictionary: [String: AnyObject]) {
super.init()
fromId = dictionary["fromId"] as? String
text = dictionary["text"] as? String
timestamp = dictionary["timestamp"] as? NSNumber
toId = dictionary["toId"] as? String
imageUrl = dictionary["imageUrl"] as? String
imageWidth = dictionary["imageWidth"] as? NSNumber
imageHeight = dictionary["imageHeight"] as? NSNumber
}
}