Swift AnyObject 无法转换为 String/Int

35
我想将JSON解析为对象,但我不知道如何将AnyObject强制转换为String或Int,因为我得到的是:
0x106bf1d07:  leaq   0x33130(%rip), %rax       ; "Swift dynamic cast failure"

使用例如:

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

我有一个ResponseParser类,里面有一个responseReminders属性,它是AnyObjects的数组,来自于AFNetworking的responseObject:

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

然后在Reminder类中,我像这样初始化它(提醒作为AnyObject,但是是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"])的结果是:Optional(3065522)

在这种情况下,我该如何将AnyObject向下转换为String或Int?

//编辑

尝试了一些方法后,我得出了以下解决方案:

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

对于整数和

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

字符串相关操作


你尝试过将其转换为可选类型吗?reminderJSON["id"] as Int? - Antonio
1
你应该将你的解决方案作为答案添加到问题中,而不是编辑你的问题。在StackOverflow上,允许/鼓励自己回答自己的问题。 - vacawama
我对于字符串使用了相同的解决方案,比进行类型转换和测试更容易! - Yariv Nissim
谢谢,但自Swift 1.2以来,as已经变成了as! - LinusGeffarth
4个回答

43
在Swift中,StringInt并不是对象。这就是为什么您会收到错误消息的原因。您需要强制转换为对象NSStringNSNumber。一旦您拥有它们,它们就可以分配给类型StringInt的变量。
我建议使用以下语法:
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
}

如果它不是对象,那么它是什么? 字符串有一个名为“hasPrefix”的方法,如何在没有类的情况下使用该方法? - Edward Anthony
6
字符串是一个结构体。在Swift中,结构体可以有方法。它们之间的区别在于传递方式:结构体是按值(复制)传递的,而类是按引用(指针)传递的。为了增加混淆,大多数情况下,字符串和NSString自动桥接,因此您通常不需要考虑这个问题。您可以将Swift字符串传递给需要NSString的可可方法,它会正常工作。这种转换实例是其中一个显示差异的情况。 - vacawama
在我的情况下,传入的JSON字典中,从服务器返回的整数值是一个字符串,因此使用".integerValue"将其转换为整数的NSString工作。 - Chris Prince
1
怎么样:如果让stringValue等于dict["id"]作为NSString转换成String的话,会怎么样呢? - devios1
这是不是和 as? String 一样的意思? - devios1
1
以前你可以将NSString赋值给String,但现在你必须进行类型转换。我相信现在只需要使用as? String就足够了。 - vacawama

5

reminderJSON["id"]给你一个AnyObject?,所以你不能将其强制转换为Int。你必须先解包它。

请执行:

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

如果您确定 JSON 中会存在 id,则可以这样做。

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

否则

我已经尝试了这两种方法 - 强制转换仍然失败,但最终这个方法可行:如果是Int类型:if let id: AnyObject = reminderJSON["id"] { self.id = Int(id as NSNumber) }如果是String类型:if let tempReceiver: AnyObject = reminderJSON["send_reminder_to"] { self.id = "(tempReceiver)" } - pJes2
在一个字典之后添加 ! as String 对我有用。但是你能解释一下为什么这是解决方案吗?我不明白它为什么有效。为什么 as String 不起作用呢? - KVISH

2
现在你只需要 import Foundation。Swift 将把值类型 (String, int) 转换为对象类型 (NSString, NSNumber)。由于 AnyObject 现在适用于所有对象,因此编译器不会抱怨。

它不能与 mytextfield.text = NSUserDefaults.standardUserDefaults().valueForKey( "mykey" ) 一起使用。 - Jose Manuel Abarca Rodríguez

1

这其实非常简单,可以在一行代码中提取、转换和解封值:if let s = d["2"] as? String,就像这样:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接