2016-09-20 4 views
1

방금 ​​Swipe 2.2에서 3.0으로 프로젝트를 변환했으며 테스트에서 새로운 예외가 발생했습니다.Swift 3 NSDictionary에서 사전 변환으로 인해 NSInvalidArgumentException이 발생합니다.

+ (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; 
} 

좀 스위프트 코드에서이 전화 해요 : : 나는 파일에서 일부 JSON에 읽어 내 시험 중 하나에 몇 가지 목표 C 코드가

let expectedResponseJSON = BZTestCase.getJSONDictionary(fromFile: responseFileName) 

이 잘 작동 가장 시간의, 그러나 나는 오류를 발생시키는 하나 개의 JSON 파일이 :

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

이에 대한 이상한 점은 오류가 생성된다는 것이다 getJSONDictionaryFromFile 메서드가 반환되고 Swift 코드의 expectedResponseJSON이 채워집니다. 나에게이 말은 문제가되는 NSDictionary에서 Dictionary으로의 변환이라고 생각됩니다. 잘못된 JSON 파일이 하나입니다 : 내가 []을 둘러싸는 가장 바깥 쪽을 제거하면

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

이 오류가 사라집니다. Swift 3에서 JSON 파일의 최상위 엔티티로 배열을 사용하는 유일한 사람이 될 수 없습니다. 제가 잘못 했나요? 이 오류를 해결하려면 어떻게해야합니까?

+0

물론 최상위 JSON 객체로 배열을 사용할 수 있습니다. 그러나 당신은 배열이 아닌 사전으로 취급해야합니다. –

답변

4

주석에서 언급 한 것처럼 getJSONDictionaryFromFileNSDictionary *을 반환하고 내 JSON 입력은 배열입니다. 유일한 수수께끼는 Swift 2.2에서이 기능이 사용 된 이유입니다! 내가 Any?을 할 expectedResponseJSON을 변경 결국, 그리고 스위프트 내 목표 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... 때문에 사용 이 코드는 테스트에서 독점적으로 사용되므로 필자 입력 내용이 예상과 다를 경우 가능한 빨리 충돌을 일으키고 싶습니다.

관련 문제