Getting NSNumber from nsdictionary in swift - ios

I have an NSDictionary which I created after parsing an XML file. It is storing some numerical value (e.g, 6757677) as a string. Now I want to read it into an NSNumber. I have tried following:
alert.versionNumber = dictRef["VersionNumber"] as! NSNumber
But I am getting following error:
Could not cast value of type '__NSCFString' (0x1081c9c50) to 'NSNumber' (0x1076abb88).
I have also tried following but getting same error:
let refID:NSNumber = dictRef["referralID"] as! NSNumber
alert.refID = refID.integerValue
These conversions were simple in Objective C but are giving me a hard time in Swift.

You need to convert the NSString into a NSNumber by taking a detour via a long long (the largest signed integer type) or double (the largest floating point type). For example:
let string : NSString = "42"
// Integer solution:
let intermediate = string.longLongValue
let number = NSNumber(longLong: intermediate)
// Floating point solution:
let intermediate2 = string.doubleValue
let number2 = NSNumber(double: intermediate2)
Note that for converting a string to its double value, you might need to use a NSNumberFormatter to correctly parse the string and handle locale-dependent differences (for example, the decimal separator is a . in the US but a , in Germany).

Try this
var num:NSNumber = NSNumber(integer:(dictRef["referralID"] as! NSString).integerValue)

let dictRef = NSDictionary(objects: ["6757677","1234567"], forKeys: ["VersionNumber", "referralID"])
if let versionNumber = dictRef.valueForKey("VersionNumber")?.integerValue {
let myNSNumber = NSNumber(integer: versionNumber)
println(myNSNumber) // 6757677
}

Related

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))"

how to get Number value form dictionary

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"]!)

swift forcing objective-c int to be assigned as Int32 then crashing

I have an objective c property that has been declared as
#property int xmBufferSize;
If I do sharedExample.xmBufferSize = 1024 it just works fine
but when I am trying to set an integer value for that property from another variable
var getThat:Int = dict["bufferSize"]!.integerValue
sharedExample.xmBufferSize = getThat
It can't do above
Cannot assign a value of type 'Int' to a value of type 'Int32'
If I force this to
sharedExample.xmBufferSize =dict["bufferSize"] as! Int32
It is crashing with Error
Could not cast value of type '__NSCFNumber' to 'Swift.Int32'
EDIT::::
Dict init, there are other objects in dict besides integers
var bufferSize:Int = 1024
var dict = Dictionary<String, AnyObject>() = ["bufferSize":bufferSize]
The value in dict is an NSNumber, which cannot be cast or directly converted to Int32. You can first obtain the NSNumber and then call intValue on it:
if let bufferSize = dict["bufferSize"] as? NSNumber {
sharedExample.xmlBufferSize = bufferSize.intValue
}
The if let … as? allows you to verify that the value is indeed an NSNumber, since (as you said) there can be other types of objects in dict. The then-branch will only execute if dict["bufferSize"] exists and is an NSNumber.
(Note: You can also try integerValue if intValue gives the wrong type, or convert the resulting integer – CInt(bufferSize.integerValue) – as needed. Swift doesn't do implicit conversions between different integer types, so you need to match exactly.)
You need to convert your NSNumber to Int32.
sharedExample.xmBufferSize = dict["bufferSize"]!.intValue
Use type conversion, not as:
sharedExample.xmBufferSize = Int32(dict["bufferSize"] as! Int)
That should work.

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)"

How do I convert an NSString to an integer using Swift?

I need to convert an NSString to an integer in Swift: Here's the current code I'm using; it doesn't work:
var variable = (NSString(data:data, encoding:NSUTF8StringEncoding))
exampeStruct.otherVariable = (variable).intValue
Variable is a normal varable, and exampleStruct is a struct elsewhere in the code with a subvariable otherVariable.
I expect it to set exampleStruct.otherVariable to an int value of the NSString, but I get the following error:
"Cannot convert the expression's type () to type Float"
How do I convert an NSString to int in Swift?
It looks to me like the problem might not be the Int conversion, but rather that the exampleStruct is expecting a Float.
If that's not the issue however (and granted, Xcode errors for Swift often seem to be more about the line number rather than about the actual problem) then something like this should work for you?
var ns:NSString = "1234"
if let i = (ns as String).toInt() {
exampleStruct.otherVariable = i
}
I know you already got your answer, but I just want to explain what (I think) might not be trivial
First, we have some NSData we want to convert to NSString, because no one guaranties the data is a valid UTF8 buffer, it return an optional
var variable = NSString(data:data, encoding:NSUTF8StringEncoding)
Which means variable: NSString?
Usually NSString is bridged to swift's String, but in this case, we use an NSString constructor - you can think about it more as a "Foundation"-like syntax that wasn't directly imported to swift (as there's no bridge for NSData)
we can still use the 'Foundation' way with NSString
if let unwrappedVariable = variable {
var number = unwrappedVariable.intValue
}
if number is a Float, but the string is a string representation of an integer
if let unwrappedVariable = variable {
var number: Float = Float(unwrappedVariable.intValue)
}
if both number and the string (representation of) are floats:
if let unwrappedVariable = variable {
var number:Float = unwrappedVariable.floatValue
}
Anyway, there's a small problem with using Foundation. For these types of conversions it has no concept of an optional value (for int, float). It will return 0 if it cannot parse a string as and integer or float. That's why it's better to use swift native String:
if let variable: String = NSString(data: data, encoding: NSUTF8StringEncoding) {
if let integer = variable.toInt() {
var integerNumber = integer
var floatNumber = Float(integer)
}
}
edit/update:
No need to use NSString when coding with Swift. You can use Swift native String(data:) initializer and then convert the string to Int:
if let variable = String(data: data, encoding: .utf8),
let integer = Int(variable) {
exampeStruct.otherVariable = integer
}
If other variable is a Float type:
if let variable = String(data: data, encoding: .utf8),
let integer = Float(variable) {
exampeStruct.otherVariable = integer
}

Resources