Swift 3 NSDictionary 到 Dictionary 的转换导致 NSInvalidArgumentException

Posted

技术标签:

【中文标题】Swift 3 NSDictionary 到 Dictionary 的转换导致 NSInvalidArgumentException【英文标题】:Swift 3 NSDictionary to Dictionary conversion causes NSInvalidArgumentException 【发布时间】:2016-09-20 13:54:00 【问题描述】:

我刚刚将我的项目从 Swift 2.2 转换为 3.0,并且在我的测试中抛出了一个新异常。我的一个测试中有一些 Objective C 代码,它从文件中读取一些 JSON:

+ (NSDictionary *)getJSONDictionaryFromFile:(NSString *)filename 
    /* some code which checks the parameter and gets a string of JSON from a file.
     * I've checked in the debugger, and jsonString is properly populated. */

    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
    return jsonDict;

我从一些 Swift 代码中调用它:

let expectedResponseJSON = BZTestCase.getJSONDictionary(fromFile: responseFileName)

大部分在大多数情况下都可以正常工作,但我有一个导致错误的JSON 文件:

failed: caught "NSInvalidArgumentException", "-[__NSSingleObjectArrayI enumerateKeysAndObjectsUsingBlock:]: unrecognized selector sent to instance 0x608000201fa0"

奇怪的是,错误是在getJSONDictionaryFromFile方法返回之后,在Swift代码中expectedResponseJSON被填充之前产生的。对我来说,这似乎是从NSDictionaryDictionary 的转换,这就是问题所在。有问题的 JSON 文件是这个:

[
  
    "status": "403",
    "title": "Authentication Failed",
    "userData": ,
    "ipRangeError": 
      "libraryName": "Name goes here",
     "libraryId": 657,
      "requestIp": "127.0.0.1"
    
  
]

如果我删除最外层的[],这个错误就会消失。我不能是唯一一个在 Swift 3 中使用数组作为 JSON 文件的***实体的人,我做错了什么吗?我可以做些什么来解决这个错误?

【问题讨论】:

当然可以使用数组作为***JSON对象。但是你必须把它当作一个数组,而不是一个字典。 【参考方案1】:

正如 cmets 中所引用的,问题在于 getJSONDictionaryFromFile 返回一个 NSDictionary * 而我的 JSON 输入是一个数组。唯一的谜团是为什么它曾经在 Swift 2.2 中工作!我最终将expectedResponseJSON 更改为Any?,并用Swift 重写了我的Objective C 代码:

class func getStringFrom(file fileName: String, fileExtension: String) -> String 
    let filepath = Bundle(for: BZTestCase.self).path(forResource: fileName, ofType: fileExtension)
    return try! NSString(contentsOfFile: filepath!, usedEncoding: nil) as String


class func getJSONFrom(file fileName: String) -> Any? 
    let json = try! JSONSerialization.jsonObject(with: (getStringFrom(file: fileName, fileExtension: ".json").data(using: .utf8))!, options:.allowFragments)
    return json

作为对可能剪切和粘贴此代码的任何人的说明,我使用 try!filepath! 而不是 try?if let...,因为此代码专门用于测试,所以我希望它崩溃为如果我的输入不是我所期望的,请尽快。

【讨论】:

以上是关于Swift 3 NSDictionary 到 Dictionary 的转换导致 NSInvalidArgumentException的主要内容,如果未能解决你的问题,请参考以下文章

Swift:将 NSDictionary 保存到文件中,因为 NSUserDefaults 会变慢

swift里nsdictionary和dictionary有啥区别

不能使用 String 类型的索引为 NSDictionary 类型的值下标。从 Swift 2.3 -> 3.2 转换时

如何将所有键和值从 Swift 中的 NSDictionary 获取到单独的字符串数组中?

如何使用 Swift 将新数组数据添加到 plist 文件中的 NSDictionary

无法弄清楚如何在 Swift 中使用 NSURLSession 将 jsonData 加载到 NSDictionary