Swift AnyObject is not convertible to String/Int
Asked Answered
E

4

35

I want to parse a JSON to object, but I have no idea how to cast AnyObject to String or Int since I'm getting:

0x106bf1d07:  leaq   0x33130(%rip), %rax       ; "Swift dynamic cast failure"

When using for example:

self.id = reminderJSON["id"] as Int

I have ResponseParser class and inside of it (responseReminders is an Array of AnyObjects, from AFNetworking responseObject):

for reminder in responseReminders {
    let newReminder = Reminder(reminderJSON: reminder)
        ...
}

Then in Reminder class I'm initialising it like this (reminder as AnyObject, but is Dictionary(String, AnyObject)):

var id: Int
var receiver: String

init(reminderJSON: AnyObject) {
    self.id = reminderJSON["id"] as Int
    self.receiver = reminderJSON["send_reminder_to"] as String
}

println(reminderJSON["id"]) result is: Optional(3065522)

How can I downcast AnyObject to String or Int in case like this?

//EDIT

After some tries I come with this solution:

if let id: AnyObject = reminderJSON["id"] { 
    self.id = Int(id as NSNumber) 
} 

for Int and

if let tempReceiver: AnyObject = reminderJSON["send_reminder_to"] { 
    self.id = "\(tempReceiver)" 
} 

for string

Etherify answered 22/8, 2014 at 14:14 Comment(4)
Have you tried casting as optionals? reminderJSON["id"] as Int?Bering
You should add your solution to your question as an answer instead of editing your question. You are allowed/encouraged to answer your own questions on StackOverflow.Pointillism
I used the same solution for String, way easier than casting and testing for types!Ancelin
Thanks, but the as is as! since Swift 1.2.Surcease
P
43

In Swift, String and Int are not objects. This is why you are getting the error message. You need to cast to NSString and NSNumber which are objects. Once you have these, they are assignable to variables of the type String and Int.

I recommend the following syntax:

if let id = reminderJSON["id"] as? NSNumber {
    // If we get here, we know "id" exists in the dictionary, and we know that we
    // got the type right. 
    self.id = id 
}

if let receiver = reminderJSON["send_reminder_to"] as? NSString {
    // If we get here, we know "send_reminder_to" exists in the dictionary, and we
    // know we got the type right.
    self.receiver = receiver
}
Pointillism answered 1/9, 2014 at 12:47 Comment(6)
If it's not object, then what is it? String has a method named "hasPrefix", how to put that method without class?Fabre
String is a struct. In Swift, structs can have methods. The difference is how they are passed: structs are passed by value (copied) and classes are passed by reference (pointer). To add to the confusion, most of the time Strings and NSStrings are bridged automatically so you usually don't have to think about it. You can pass a Swift String to a cocoa method that takes NSString and it just works. This casting instance is one of those cases where the difference shows up.Pointillism
In my case, the incoming JSON dictionary had the integer value coming back from the server as a string, so as? NSString", followed by conversion to an integer using .integerValue worked.Grub
How about: if let stringValue = dict["id"] as? NSString as String? { … }?Languish
Or is that just the same as as? String?Languish
You used to be able to assign an NSString to a String, but now you have to cast it. I believe just as? String should be sufficient now.Pointillism
S
5

reminderJSON["id"] gives you an AnyObject?, so you cannot cast it to Int You have to unwrap it first.

Do

self.id = reminderJSON["id"]! as Int

if you're sure that id will be present in the JSON.

if id: AnyObject = reminderJSON["id"] {
    self.id = id as Int
}

otherwise

Schoenburg answered 22/8, 2014 at 14:48 Comment(2)
I've tried both of this - the casting still fails, but at the end this works: if let id: AnyObject = reminderJSON["id"] { self.id = Int(id as NSNumber) } for Int and if let tempReceiver: AnyObject = reminderJSON["send_reminder_to"] { self.id = "(tempReceiver)" } for stringEtherify
adding ! as String works for me after a Dictionary. But can you explain why its the solution? I don't get why it works. Why doesn't as String work?Artilleryman
S
2

Now you just need to import Foundation. Swift will convert value type(String,int) into object types(NSString,NSNumber).Since AnyObject works with all objects now compiler will not complaint.

Should answered 5/6, 2015 at 6:51 Comment(1)
It doesn't work with mytextfield.text = NSUserDefaults.standardUserDefaults().valueForKey( "mykey" ).Mecklenburg
A
1

This is actually pretty simple, the value can be extracted, casted, and unwrapped in one line: if let s = d["2"] as? String, as in:

var d:[String:AnyObject] = [String:AnyObject]()
d["s"] = NSString(string: "string")

if let s = d["s"] as? String {
    println("Converted NSString to native Swift type")
}
Azoic answered 9/7, 2015 at 20:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.