how to get Number value form dictionary - ios

I am accessing data from JSON and storing it in dictionary 1 and passing this dictionary 1 to another view controller's dictionary 2. The view controller has all the details mainly 12 labels. I have managed to access the strings but i am not able to get the number values. Please have a look at the code.
DetailsViewController
var dict2 = [String : AnyObject]()
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.lblTopName.text = self.dict2["toponymName"] as? String
self.lblFcodeName.text = self.dict2["fcodeName"] as? String
self.lblName.text = self.dict2["name"] as? String
self.lblCountryCode.text = self.dict2["countrycode"] as? String
self.lblFCL.text = self.dict2["fcl"] as? String
self.lblFclName.text = self.dict2["fclName"] as? String
self.lblWikipedia.text = self.dict2["wikipedia"] as? String
self.lblFcode.text = self.dict2["fcode"] as? String
self.lblLongitude.text = self.dict2["lng"] as? String
Note. The last line of code that is longitude a number value. If I replace String with NSNumber it gives me the following error:
Cannot assign value of type NSNumber to type String

Forced cast should be avoided as much as possible, as it can lead to unexpected crashes. (self.dict2["lng"] as! NSNumber) will crash your application if for some reason the dictionary ends up without the lng key.
Your last line should be:
self.lblLongitude.text = self.dict2["lng"]?.description
This is guaranteed not to crash, as description exists on any object, and in case the dictionary somehow doesn't contain the "lng" key, you'll get a simple nil to assign to text.

plese try this if self.dict2["lng"] never null
self.lblLongitude.text = (self.dict2["lng"] as! NSNumber).stringValue
else if can be null then
self.lblLongitude.text = self.dict2["lng"]?.description

you can get integer value from dictionary like
int value = dict["integerValue"].integerValue // or doubleValue etc
and if you need string it can be like
self.lblLongitude.text = "\(self.dict2["lng"]. doubleValue)"

You can write like this
self.lblLongitude.text = String(format: "%f",self.dict2["lng"]!)

Related

How can I access an struct attribute from an array?

What I want to do is to, after storing several objects of type CodigosAutorizacion inside an array:
for value in 0..<(array.count) {
let codeArray = CodigosAutorizacion(
code: validateData!["codigo"] as? String,
codeCancel: validateData!["cancela_codigo"] as? String,
codeSite: validateData!["cod_sitio"] as? String,
codeSiteCancel: validateData!["cancela_cod_sitio"] as? String,
instance: validateData!["instancia"] as? String
)
codes.append(codeArray)
}
Access the object attributes from the array like this:
codeCell.codigoSitio.text = codes[indexPath.row].instance
This piece throws me the next errors
-No exact matches in call to subscript
-Reference to member 'instancia' cannot be resolved without a contextual type
this is because ´codes´ is an array and not a CodigosAutorizacion type
Storing these objects in an array is important because I will need to generate a table with several of this CodigosAutorizacion objects. Is there any way this can be possible?
var codes = [CodigosAutorizacion]()
for value in 0..<(array.count) {
let codeArray = CodigosAutorizacion(
code: validateData!["codigo"] as? String,
codeCancel: validateData!["cancela_codigo"] as? String,
codeSite: validateData!["cod_sitio"] as? String,
codeSiteCancel: validateData!["cancela_cod_sitio"] as? String,
instance: validateData!["instancia"] as? String
)
codes.append(codeArray)
}
-- Try this --
Fixed! it was a problem with the codes array declaration, it was not supposed to be var codes: Array<Any> but instead var codes: Array<CodigosAutorizacion> in order to access CodigosAutorizacion's properties

iOS Swift: Could not cast value type '__NSCFNumber' to 'NSString'

I am retrieving a number value from my Firebase database (JSON db) and then displaying this number into a textField, although I get this error when I try to display it.
Could not cast value type '__NSCFNumber' to 'NSString'
How can I properly convert the retrieved value to a String, taking into consideration that this value maybe change between a String and a Number when I retrieve it.
Here is my code:
let quantity = child.childSnapshot(forPath: "quantity").value // Get value from Firebase
// Check if the quantity exists, then add to object as string.
if (!(quantity is NSNull) && ((quantity as! String) != "")) {
newDetail.setQuantity(quantity: quantity as! String)
}
The error is saying that your quantity is Number and you cannot directly convert number to String, try like this.
newDetail.setQuantity(quantity: "\(quantity)")
Or
if let quantity = child.childSnapshot(forPath: "quantity").value as? NSNumber {
newDetail.setQuantity(quantity: quantity.stringValue)
}
else if let quantity = child.childSnapshot(forPath: "quantity").value as? String {
newDetail.setQuantity(quantity: quantity)
}
Or With Single if statement
if let quantity = child.childSnapshot(forPath: "quantity").value,
(num is NSNumber || num is String) {
newDetail.setQuantity(quantity: "\(quantity))
}
Using second and third option there is no need to check for nil.
Swift 4:
let rollNumber:String = String(format: "%#", rollNumberWhichIsANumber as! CVarArg)
You may convert your NSNumber value to string like this too, its more traditional and basic approach to format a string
newDetail.setQuantity(String(format: "%#", quantity))
Swift 4.
newDetail.setQuantity(String(describing: rollNumberWhichIsANumber))
In swift 4.1 and Xcode 9.4.1
newDetail.setQuantity(quantity: "(quantity)")
We can convert to string like this "\(quantity)"
let session_id : Int32 = (jsonObject.value(forKey: "id") as! NSNumber).int32Value
Swift 5:
I manage to fix it buy using .description when interpolating the UserDefaults value into a label converting from Int to String.
working code
highScoreLabel?.text = "HiScore: \(hiScoreValue.description)"
old code
highScoreLabel?.text = "HiScore: \(String(describing: hiScoreValue))"

Cast from FIRRemoteConfigValue to unrelated type String always fails : Firebase, Swift

I know this is a duplicate of Cast from FIRRemoteConfigValue to unrelated type String always fails. But the accepted answer there is that it's just a bug.
Which i don't think it is.
According to another solution, I have to force-cast the datatype every time I retrieve or instantiate a variable. I was hoping to find a different and elegant solution to this.
Everything was working fine, but after I installed Pod 'FirebaseRemoteConfig', I am having this warning on every line I instantiate a variable with a Snapshot value that I receive.
Cast from FIRRemoteConfigValue to unrelated type String always fails
When I run my app, it crashes there.
Bugged Code
FIRDatabase.database().reference().child("Posts").observe(.value, with: {(recievedSnap) in
if recievedSnap.exists(){
if let dict = recievedSnap.value as? [String:AnyObject]{
for each in dict{
let str = each.value["text"] as! String //Line of warning(and crash when the app is run)
}
}
}
})
Working Code
FIRDatabase.database().reference().child("Posts").observe(.value, with: {(recievedSnap) in
if recievedSnap.exists(){
if let dict = recievedSnap.value as? [String:AnyObject]{
for each in dict{
if let eachValue = each.value as? [String:AnyObject]{
let str = eachValue["text"] as! String
}
}
}
}
})
I am looking for explanation as to:
What changed after Pod 'FirebaseRemoteConfig' installation that it started giving me this error?
Why am I required to force cast every time I initialize a variable?
Is there a better approach?
Finally got the solution...
Use valueForKey Instead of [] bracket access value, because FIRRemoteConfigValue dont have support to access value using []
Then all value goes away...
For Example
Warning code...
Below code give a warning...
let id = snapshot.value!["senderId"] as! String
let text = snapshot.value!["text"] as! String
let locationId = snapshot.value!["location"] as! String
Use Like this
let id = snapshot.value.valueForKey("senderId") as! String
let text = snapshot.value.valueForKey("text") as! String
let locationId = snapshot.value.valueForKey("location") as! String
Warming is not appear longer.....
NOTE: If you use like above then old code also working fine...

NSMutableDictionary treats NSString value as NSNumber

I have the following value in a NSMutableDictionary - see image
I'm attempting to get at "a" thus:
let a = dictionary.objectForKey("a") as! String
the app crashes at this point with
Could not cast value of type '__NSCFNumber' (0x...) to 'NSString' (0x...).
other numbers inside "" are treated as strings as are numbers outside of strings cast to String without any issue.
Can anyone let me know what's going on? And how to get at these values easily?
The value is an NSNumber, not an NSString. You can use stringValue to convert it:
if let a = d["a"] as? NSNumber {
let aString = a.stringValue
println(aString) // -1
} else {
// either d doesn't have a value for the key "a", or d does but the value is not an NSNumber
}
If you're sure it exists and is an NSNumber, you can use forced unwrapping, forced casting, and string interpolation:
let a = d["a"]! as! NSNumber
let aString = "\(a)"

Swift optionals: language issue, or doing something wrong?

I am doing what I believe to be a very simple task. I'm trying to get a value out of a dictionary if the key exists. I am doing this for a couple keys in the dictionary and then creating an object if they all exist (basically decoding a JSON object). I am new to the language but this seems to me like it should work, yet doesn't:
class func fromDict(d: [String : AnyObject]!) -> Todo? {
let title = d["title"]? as? String
// etc...
}
It gives me the error: Operand of postfix ? should have optional type; type is (String, AnyObject)
HOWEVER, if I do this, it works:
class func fromDict(d: [String : AnyObject]!) -> Todo? {
let maybeTitle = d["title"]?
let title = maybeTitle as? String
// etc...
}
It appears to be basic substitution but I may be missing some nuance of the language. Could anyone shed some light on this?
The recommended pattern is
if let maybeTitle = d["title"] as? String {
// do something with maybeTitle
}
else {
// abort object creation
}
It is possibly really a question of nuance. The form array[subscript]? is ambiguous because it could mean that the whole dictionary (<String:AnyObject>) is optional while you probably mean the result (String). In the above pattern, you leverage the fact that Dictionary is designed to assume that accessing some key results in an optional type.
After experimenting, and noticing that the ? after as is just as ambiguous, more, here is my solution:
var dictionary = ["one":"1", "two":"2"]
// or var dictionary = ["one":1, "two":2]
var message = ""
if let three = dictionary["three"] as Any? {
message = "\(three)"
}
else {
message = "No three available."
}
message // "No three available."
This would work with all non-object Swift objects, including Swift Strings, numbers etc. Thanks to Viktor for reminding me that String is not an object in Swift. +
If you know the type of the values you can substitute Any? with the appropriate optional type, like String?
There are a few of things going on here.
1) The ? in d["title"]? is not correct usage. If you're trying to unwrap d["title"] then use a ! but be careful because this will crash if title is not a valid key in your dictionary. (The ? is used for optional chaining like if you were trying to call a method on an optional variable or access a property. In that case, the access would just do nothing if the optional were nil). It doesn't appear that you're trying to unwrap d["title"] so leave off the ?. A dictionary access always returns an optional value because the key might not exist.
2) If you were to fix that:
let maybeTitle = d["title"] as? String
The error message changes to: error: '(String, AnyObject)' is not convertible to 'String'
The problem here is that a String is not an object. You need to cast to NSString.
let maybeTitle = d["title"] as? NSString
This will result in maybeTitle being an NSString?. If d["title"] doesn't exist or if the type is really NSNumber instead of NSString, then the optional will have a value of nil but the app won't crash.
3) Your statement:
let title = maybeTitle as? String
does not unwrap the optional variable as you would like. The correct form is:
if let title = maybeTitle as? String {
// title is unwrapped and now has type String
}
So putting that all together:
if let title = d["title"] as? NSString {
// If we get here we know "title" is a valid key in the dictionary, and
// we got the type right. title has now been unwrapped and is ready to use
}
title will have the type NSString which is what is stored in the dictionary since it holds objects. You can do most everything with NSString that you can do with String, but if you need title to be a String you can do this:
if var title:String = d["title"] as? NSString {
title += " by Poe"
}
and if your dictionary has NSNumbers as well:
if var age:Int = d["age"] as? NSNumber {
age += 1
}

Resources