Logo Questions Linux Laravel Mysql Ubuntu Git Menu

Cannot downcast from 'AnyObject' whilst parsing JSON array





I'm in the process of trying to migrate an existing project to Swift, its more of a learning exercise but I think I've hit a problem which seems pretty basic and I think it may relate to my lack of understanding of AnyObject.

I've created a object that consists of a number of variables and is initialised as:

var customObject:MycustomObject = MYcustomObject()

I'm then using NSURLConnection to retrieve JSON data and this all appears to be working correctly as the jsonArray is being populated with data

jsonArray = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSArray

I'm then looping through the array and attempting to parse the data and this is where I'm experiencing problems, the for loop defaults details to AnyObject.

for details:AnyObject in jsonArray {
    parseDetail(details as NSDictionary)

The problem relates to the integerValue, its generating an "Cannot downcast from 'AnyObject' to non-@objc...." error

func parseDetail(element: NSDictionary ) {
        self.customObject.stringValue      = element["id"] as String
        self.customObject.integerValue     = element["type"] as Integer

There also seems to be some differences in the way NSString & String are working, my understanding so far is that when using Swift I should be using the native types Sting, Float Integer etc etc. If I use NSString the stringValue displays correctly in the debug window but when using the type String I receive the following:

  core = {
    _baseAddress = Builtin.RawPointer = 0x0b227f49
    _countAndFlags = 1073741828
    _owner = Some {
      Some = (instance_type = Builtin.RawPointer = 0x0b227f40 -> 0x006d58f0 (void *)0x006d58c8:          __NSCFString)

Sorry this is a little long but is there any info regarding threading, this is my next challenge?

NSThread.detachNewThreadSelector(Selector: parseDetail(), toTarget: self, withObject: nil)
like image 790
Duncan Hill Avatar asked Jun 08 '14 22:06

Duncan Hill

1 Answers

Here's a little example that does the job. First, here's a model class for our purposes:

class CustomObject {
    var name: String = ""
    var age : Int    = 0

    init(json: Dictionary<String, AnyObject>) {
        name = json["name"] as NSString
        age  = (json["age" ] as NSNumber).integerValue

As you can see, we still need to deal with NSNumbers and NSStrings since NSJSONSerialization is not yet updated to the Swift types.

Next, a little json.txt file residing in our project:


And last, the parser, right in application launch for a quick test:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    var filePath  = NSBundle.mainBundle().pathForResource("json", ofType:"txt")
    var data      = NSData(contentsOfFile:filePath)
    var json      = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as Array<Dictionary<String, AnyObject>>

    var customObjects = json.map { dict in CustomObject(json: dict) }


    return true

This will print:

like image 141
Jean Le Moignan Avatar answered Nov 11 '22 06:11

Jean Le Moignan