2016-09-24 63 views
1

升級到iOS10後,用戶開始抱怨我的應用程序崩潰。 我在模擬器上使用iOS10測試它,實際上應用程序崩潰時顯示消息「無法將類型'__NSArrayI'的值轉換爲'NSMutableArray''」。這裏是我的代碼,請大家幫忙:需要調整NSJSONSerialization到iOS10

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

使用SWIFT本地集合類型,而不是不相關類型的缺乏(可變)基金會類型,可以解決您的問題。 – vadian

+0

我有一個類似的問題,我的JSON解析器現在正在生成NSDictionary而不是NSMutableDictionary。我需要繼續使用可變字典,但我認爲解決方案應該很簡單,因爲您可以創建可變副本:mutableDictionary = dictionary.mutableCopy()。我假設你可以爲NSArray做一些平行的事情。一旦我有機會更詳細地瞭解這一點,我會讓你知道我是怎麼得到的... – Sparky

回答

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!轉換會導致一些奇怪的崩潰,當服務器出現故障,但這是另外一個問題,所以我把它那裏。)

+0

這很完美!謝謝!!! – Ran