NSMutableDictionary treats NSString value as NSNumber - ios

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

Related

Casting Int database value into CoreData issue

I am trying to load some values from my firebase database directly into CoreData, the value in question is an integer but the issue is CoreData wants a Int64, Int32, or Int16, and it's not possible to downcast Ints in swift, So I am getting an error on the line of code where I assign the CoreData attribute to the database value. The database returns 0 (value will only be 0 or 1). Casting the database value as an Int64 is giving me an error. The bilateral_unilat attribute is of type Int64. How can I save an Int value into CoreData?
cdExercise.bilat_unilat = (exercise.childSnapshot(forPath: "bilat_unilat").value as! Int64)
this is the error:
Could not cast value of type 'NSTaggedPointerString' (0x7fff87a91958) to 'NSNumber' (0x7fff87b50b80).
in the debugger window I can print out a value of 0, which is the expected value, with this line of code:
po (exercise.childSnapshot(forPath: "bilat_unilat").value as! NSNumber)
Not sure what the issue is here
If you're attempting to get to a NSNumber as the end result, here's a couple of options
let aInt = snapshot.childSnapshot(forPath: "bilat_unilat").value as? Int ?? 0
let aNum = NSNumber(integerLiteral: aInt)
or just do it directly
let aNum = snapshot.childSnapshot(forPath: "bilat_unilat").value as! NSNumber
*note I omitted error handling for brevity and assumes the value of the bilat_unilat node is in fact an Int
The error
Could not cast value of type 'NSTaggedPointerString' (0x7fff87a91958) to 'NSNumber' (0x7fff87b50b80)
is misleading.
value is apparently NSNumber so cast it to NSNumber and then to Int64
let bilatUnilat = exercise.childSnapshot(forPath: "bilat_unilat").value as! NSNumber
cdExercise.bilat_unilat = bilatUnilat as! Int64
If the value is only 0 or 1 I recommend to declare the attribute as Bool
let bilatUnilat = exercise.childSnapshot(forPath: "bilat_unilat").value as! NSNumber
cdExercise.bilat_unilat = bilatUnilat == 1
And please name the Core Data attributes according to the naming convention lowerCamelCased

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

Getting NSNumber from nsdictionary in swift

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
}

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.

Swift NSArray subscript a value of type AnyObject

This my my NSArray
var RidesData:NSArray = []
It is used to store an JSON Array i have converted
RidesData = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as! NSArray
Sample of the Array
Optional((
{
ContentType = USSShow;
Name = "Lake Hollywood Spectacular\U00ae (Seasonal Show)";
NextShowTime = "8:00pm";
NextTimeSlot = "";
QueueTime = "";
TimeSlot = "";
},
I am trying to get the Name value using this code
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"]
cell.textLabel!.text = RideName
However i am getting this error
Cannot subscript a value of type 'AnyObject?!' with an index type of 'int'
From what i have searched, i believe that i am unable to subscript because it is an optional but when i tried to unwrap it with ! it gives me this error
Operand of postfix "!" should have optional type; type is 'NSArray'
How can i solve this problem?
Try:
let RideName = RidesData[indexPath.section]["Data"]??[indexPath.row]?["Name"] as? String
Since RidesData[indexPath.section]["Data"] is AnyObject?! you have to unwrap it twice.
Why AnyObject?! ? Because RidesData[indexPath.section] is AnyObject, and AnyObject may or may not have subscript. So, the first ? means, "If it has subscript", and the second means "If subscript returns non nil".
Replace this line
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"]
with this
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"] as! String
RidesData[indexPath.section]["Data"] is of type AnyObject?! and then you try to access the indexPath.row element. You need to first unwrap this part.
Try this:
let RideName = RidesData[indexPath.section]["Data"]?[indexPath.row]["Name"]
The problem is with the cast, the array RidesData is an optional array: [AnyObject]?.
So you must write it like this:-
let RideName = RidesData[indexPath.section]["Data"][indexPath.row]["Name"] as! String

Resources