2
votes

I have an Int that I saved in Parse as an AnyObject. When I retrieve the AnyObject? and try to cast it as a String, NSString, NSNumber, or anything else, I keep getting an EXC_Breakpoint as the casting is returning Nil and there's a "Swift dynamic cast failed" error".

I tried to create this simple test to figure out which part fails, but the crazy thing is that this test will pass where seemingly all the steps are the same:

func testAnyObjectCasting(){
    var myInt32: Int32 = 265
    var myInt: Int = Int(myInt32)
    var myAnyObject: AnyObject? = myInt as AnyObject
    var myAnyArray: [[AnyObject]] = [[AnyObject]]()
    myAnyArray.append(["something", myAnyObject!])
    println(myAnyObject)
    var myOtherAnyObject: AnyObject? = myAnyArray[0][1]
    println(myOtherAnyObject)
    var myString:NSNumber? = myOtherAnyObject as? NSNumber
    println(myString)
    var myInt2: Int = myString! as Int
}

Here's the relevant code snippets from my logic, and notes that println() works fine until the downcast to NSNumber, at which time Nil is returned:

   //ABRecordGetRecordId returns an ABRecordID, which is of type Int32
   //This value that's stored in the 2nd column of the multiDim [[AnyObject]] 
   var personId: Int = Int(ABRecordGetRecordID(person))

   //This is a call to a Parse object, which returns an AnyObject.  I then cast that to
   //a multidimensional array AnyObject as that's the true structure of the data in swift speak
   var deviceContacts: [[AnyObject]] = device?[deviceContactsFieldName] as [[AnyObject]]

   //This returns the expected value, which in my broader test case is 99999, which is supported by Int
   var i:Int = 1
   println("the value in device contacts \(i) column 1 is: \(deviceContacts[i][1])")

   //This takes a single cell value from the multidim array and puts it in an optional AnyObject
   var valueInParse: AnyObject? = deviceContacts[i][1]

   //This still returns 99999
   println(valueInParse)

   //This is where 99999 is replaced with nil.  Any ideas?
   var valueNSNumberInParse: NSNumber? = valueInParse as? NSNumber

   //Nil :(
   println(valueNSNumberInParse)

   //Exception as I'm trying to unwrap nil :( 
   var unwrappedNSNumber:NSNumber = valueNSNumberInParse!

Part of my frustration is that I don't understand why println() works fine for AnyObject but all the casting fails. Clearly there's code that can interpret the value as a string to show for println, but that syntax eludes me for proper casting.

1
Set a breakpoint. What is valueNSNumberInParse? - Paulw11
I suspect valueInParse is the string "99999" which when conditionally cast as NSNumber returns nil because the cast fails. - vacawama
Thanks for the fast response! Foundation.NSValue = (NSValue) (null). println(valueInParse) displays "Optional(99999)". - John Kucera
@vacawama - when I change the cast from NSNumber to NSString and then later cast to String, I get a different error of "fatal error: unexpectedly found nil while unwrapping an Optional" - John Kucera
NSValue is effectively a byte buffer that represents an intrinsic type - developer.apple.com/library/mac/documentation/Cocoa/Reference/…. Why don't you just convert the value to an NSNumber before storing it in Parse? - Paulw11

1 Answers

2
votes

Because you have saved an Int into Parse and an Int is not an object it had to be converted to an object. It seems that the Parse framework has converted it to an NSValue, which is effectively a byte buffer that represents an intrinsic type.

You could try and convert these bytes back to an Int, but it is easier and better to encode the value into an NSNumber before storing it in the Parse object - then you will be easily able to handle it when you retrieve the object.