将Dictionary转换为AnyObject时编译错误?

时间:2014-11-03 16:08:34

标签: ios swift casting nsjsonserialization

我试图在Swift中进行一个简单的扩展,这样可以很容易地使用NSJSONSerialization.dataWithJSONObject将Dictionary转换为JSON NSData。

extension Dictionary {
    func toJSONData() -> NSData! {
        return NSJSONSerialization.dataWithJSONObject(self, options: nil, error: nil)
    }
}

我无法弄清楚为什么这不会编译。它给了我一个类型错误:

Cannot downcast from 'Dictionary<Key, Value>' to non-@objc protocol type 'AnyObject'

任何想法?我已经用Google搜索过,无法找到任何内容。

注意:

我已经对此进行了测试,它运行得很好:

return NSJSONSerialization.dataWithJSONObject(["":""], options: nil, error: nil)

4 个答案:

答案 0 :(得分:4)

(来自我的上述评论:)问题是并非所有Swift词典都可以转换为AnyObject,只能转换为[NSObject: AnyObject]类型。并且定义仅适用于某些受限泛型类型的泛型类型的扩展似乎是不可能的(对于数组扩展,存在类似的Q&amp; A)。

您可以使用函数(如Nate在其答案中建议的那样),或定义扩展名 代替NSDictionary


更新 Swift 2:从Swift 2开始,可以定义泛型类型的扩展名,该扩展名仅适用于某些受限制的泛型类型:

extension Dictionary where Key : NSObject, Value : AnyObject {
    func toJSONData() -> NSData! {
        return try? NSJSONSerialization.dataWithJSONObject(self, options: [])
    }
}

然后

let d1 = ["foo" : "bar"].toJSONData()

编译并按预期工作,但

struct Bar {} 
let d2 = [ "foo" : Bar() ].toJSONData()

无法编译,因为Bar()不是AnyObject

答案 1 :(得分:1)

编译器抱怨,因为Dictionary(在其通用形式中)理论上可以保持不可桥接类型,如Swift枚举。您可以定义顶级函数,并以这种方式对字典的键类型和值类型设置约束:

func toJSONData<T1: _ObjectiveCBridgeable, T2: _ObjectiveCBridgeable>(dict: [T1: T2]) -> NSData! {
    return NSJSONSerialization.dataWithJSONObject(dict, options: nil, error: nil)
}

答案 2 :(得分:1)

您是否考虑过扩展NSData? 结果代码非常简洁:

extension NSData {
    convenience init(jsonDictionary: [String:AnyObject]) throws {
        self.init(data:
            try NSJSONSerialization.dataWithJSONObject (
                jsonDictionary,
                options: NSJSONWritingOptions(rawValue: 0)
            ))
    }
}

用法:

let jsonData = try NSData(jsonDictionary: ["foo": 313, "fee": "bar"])

答案 3 :(得分:-1)

func simplePostMethod()  
{

let url : URL = URL(string: "writ your URL here")!

var request = URLRequest(url: url)

let session = URLSession.shared

request.httpMethod = "POST"


// Below are input parameter, you can put your input parameter.

 let params = ["name":"hijk", "nickname":"hijk","password":"123456","gender":"male","dob":"1989-02-28","email":"hijk@gmail.com","device_id":"sffdg5645445","os":"ios","social_id":"sdjaljdlasldklsdsdls"] as Dictionary<String, String>


        do{
            request.httpBody =  try JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions.prettyPrinted)
        }
        catch
        {

        }
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        let  task = session.dataTask(with: request, completionHandler: {(data,response,error) in


            if (data != nil)
            {
                do{
                    let dict =  try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableLeaves)
                    print(dict);
                }
                catch
                {

                }

            }

        }
        )

        task.resume()
    }