需要将NSJSONSerialization调整为iOS10

时间:2016-09-24 20:14:45

标签: swift ios10

升级到iOS10后,用户开始抱怨我的应用崩溃了。 我正在模拟器上使用iOS10测试它,实际上应用程序崩溃了一条消息“无法将类型'_NSNSrrayI'的值转换为'NSMutableArray'”。这是我的代码,请帮助:

import Foundation

protocol getAllListsModel: class {
    func listsDownloadingComplete(downloadedLists: [ContactsList])
}

class ListsDownloader: NSObject, NSURLSessionDataDelegate{

    //properties

    weak var delegate: getAllListsModel!

    var data : NSMutableData = NSMutableData()

    func downloadLists() {

        let urlPath: String = "http://..."
        let url: NSURL = NSURL(string: urlPath)!
        var session: NSURLSession!
        let configuration =     NSURLSessionConfiguration.ephemeralSessionConfiguration()     //defaultSessionConfiguration()


    session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)

    let task = session.dataTaskWithURL(url)

    task.resume()

}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
    self.data.appendData(data);
}

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
    if error != nil {
        print("Failed to download data")
    }else {
        self.parseJSON()
        print("Lists downloaded")
    }

}
func parseJSON() {

    var jsonResult: NSMutableArray = NSMutableArray()

    do{
        try jsonResult =  NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as! NSMutableArray

        } catch let error as NSError {
        print(error)
        }

        var jsonElement: NSDictionary = NSDictionary()
        var downloadedLists: [ContactsList] = []

        for i in 0...jsonResult.count-1 {

            jsonElement = jsonResult[i] as! NSDictionary

            let tempContactsList = ContactsList()

            //the following insures none of the JsonElement values are nil through optional binding
            let id = jsonElement["id"] as? String
            let name = jsonElement["name"] as? String
            let pin = jsonElement["pin"] as? String
            let lastUpdated = jsonElement["created"] as? String
            let listAdminDeviceID = jsonElement["admin"] as? String

            tempContactsList.id = id
            tempContactsList.name = name
            tempContactsList.pin = pin
            tempContactsList.lastUpdated = lastUpdated
            tempContactsList.listAdmin = listAdminDeviceID

            downloadedLists.append(tempContactsList)

        }

        dispatch_async(dispatch_get_main_queue(), { () -> Void in

            self.delegate.listsDownloadingComplete(downloadedLists)

        })
    }
}

1 个答案:

答案 0 :(得分:2)

即使在iOS 9中,也没有保证NSJSONSerialization.JSONObjectWithData(_:options:)会返回可变对象。您应该已指定NSJSONReadingOptions.MutableContainers

在您的代码中,您没有修改jsonResult,这意味着您无需将其声明为NSMutableArray。只需将NSMutableArray替换为NSArray,然后您就无需指定NSJSONReadingOptions.MutableContainers

但正如vadian建议的那样,最好使用Swift类型而不是NSArrayNSDictionary。此代码应在iOS 9和10中都有效。

func parseJSON() {

    var jsonResult: [[String: AnyObject]] = [] //<- use Swift type

    do{
        try jsonResult =  NSJSONSerialization.JSONObjectWithData(self.data, options: []) as! [[String: AnyObject]] //<- convert to Swift type, no need to specify options

    } catch let error as NSError {
        print(error)
    }

    var downloadedLists: [ContactsList] = []

    for jsonElement in jsonResult { //<- your for-in usage can be simplified

        let tempContactsList = ContactsList()

        //the following insures none of the JsonElement values are nil through optional binding
        let id = jsonElement["id"] as? String
        let name = jsonElement["name"] as? String
        let pin = jsonElement["pin"] as? String
        let lastUpdated = jsonElement["created"] as? String
        let listAdminDeviceID = jsonElement["admin"] as? String

        tempContactsList.id = id
        tempContactsList.name = name
        tempContactsList.pin = pin
        tempContactsList.lastUpdated = lastUpdated
        tempContactsList.listAdmin = listAdminDeviceID

        downloadedLists.append(tempContactsList)

    }

    dispatch_async(dispatch_get_main_queue(), { () -> Void in

        self.delegate.listsDownloadingComplete(downloadedLists)

    })
}

试试这个并在iOS 10设备上查看。

(当您的服务器出现故障时,as!转换会导致一些奇怪的崩溃,但这将是另一个问题,所以我会将其保留在那里。)