2017-06-12 64 views
0

错误使用NSCoder存档从JSON数组自定义对象时会导致系统崩溃。斯威夫特NSCoder NSKeyArchiver:意外发现零而展开

错误导致崩溃:

错误的

fatal error: unexpectedly found nil while unwrapping an Optional value

代码:我列入retrieveData()的完整代码

// NSCoding *Error causes Crash here* 
let blogList: NSObject = ((jsonArray[i]) as! NSObject).value(forKey: "blogList") as! NSObject 

MainController.swift

// Retrieving Data from Server *Clean Code* 
func retrieveData() { 

    let getDataURL = "http://blogtest.com/receiving.php" 
    let url: NSURL = NSURL(string: getDataURL)! 

    do { 
     let data: Data = try Data(contentsOf: url as URL) 
     jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray 

     // Looping through jsonArray 
     for i in 0..<jsonArray.count { 

      // Create Blog Object 
      let bID: String = (jsonArray[i] as AnyObject).object(forKey: "id") as! String 
      let bName: String = (jsonArray[i] as AnyObject).object(forKey: "blogName") as! String 
      let bStatus1: String = (jsonArray[i] as AnyObject).object(forKey: "blogStatus1") as! String 
      let bStatus2: String = (jsonArray[i] as AnyObject).object(forKey: "blogStatus2") as! String 
      let bURL: String = (jsonArray[i] as AnyObject).object(forKey: "blogURL") as! String 
      let bType: String = (jsonArray[i] as AnyObject).object(forKey: "blogType") as! String 
      let bDate: String = (jsonArray[i] as AnyObject).object(forKey: "blogDate") as! String 
      let bPop: String = (jsonArray[i] as AnyObject).object(forKey: "blogPop") as! String 

      // NSCoding *Error causes Crash here* 
      let blogList: NSObject = ((jsonArray[i]) as! NSObject).value(forKey: "blogList") as! NSObject 

      // Add Blog Objects to mainArray 
      mainArray.append(Blog(blogName: bName, andBlogStatus1: bStatus1, andBlogStatus2: bStatus2, andBlogURL: bURL, andBlogID: bID, andBlogType: bType, andBlogDate: bDate, andBlogPop: bPop, blogList: blogList as! [Blog])) 
     } 
    } 
    catch { 
     print("Error: (Retrieving Data)") 
    } 
    myTableView.reloadData() 
} 

Blog.swift - 手柄博客自定义对象

import UIKit 

class Blog: NSObject, NSCoding { 

// Strings 
var blogName: String 
var blogStatus1: String 
var blogStatus2: String 
var blogURL: String 
var blogID: String 
var blogType: String 
var blogDate: String 
var blogPop: String 
var blogList : [Blog] // NSCoding 

// Converting Strings into Objects 
init(blogName bName: String, 
    andBlogStatus1 bStatus1: String, 
    andBlogStatus2 bStatus2: String, 
    andBlogURL bURL: String, 
    andBlogID bID: String, 
    andBlogType bType: String, 
    andBlogDate bDate: String, 
    andBlogPop bPop: String, 
    blogList : [Blog]) // To NSCoding 
{ 

    self.blogName = bName 
    self.blogStatus1 = bStatus1 
    self.blogStatus2 = bStatus2 
    self.blogURL = bURL 
    self.blogID = bID 
    self.blogType = bType 
    self.blogDate = bDate 
    self.blogPop = bPop 
    self.blogList = blogList // NSCoding 
    super.init() 
} 

// NSCoding 
convenience required init?(coder aDecoder: NSCoder) { 
    self.init (coder : aDecoder) 
    self.blogName = aDecoder.decodeObject(forKey: "blogName") as! String 
    self.blogStatus1 = aDecoder.decodeObject(forKey: "blogStatus1") as! String 
    self.blogStatus2 = aDecoder.decodeObject(forKey: "blogStatus2") as! String 
    self.blogURL = aDecoder.decodeObject(forKey: "blogURL") as! String 
    self.blogID = aDecoder.decodeObject(forKey: "blogID") as! String 
    self.blogType = aDecoder.decodeObject(forKey: "blogType") as! String 
    self.blogDate = aDecoder.decodeObject(forKey: "blogDate") as! String 
    self.blogPop = aDecoder.decodeObject(forKey: "blogPop") as! String 
    self.blogList = aDecoder.decodeObject(forKey: "blogs") as! [Blog] 
} 

func encode(with aCoder: NSCoder) { 
    aCoder.encode(blogName, forKey: "blogName") 
    aCoder.encode(blogStatus1, forKey: "blogStatus1") 
    aCoder.encode(blogStatus2, forKey: "blogStatus2") 
    aCoder.encode(blogURL, forKey: "blogURL") 
    aCoder.encode(blogID, forKey: "blogID") 
    aCoder.encode(blogType, forKey: "blogType") 
    aCoder.encode(blogDate, forKey: "blogDate") 
    aCoder.encode(blogPop, forKey: "blogPop") 
    aCoder.encode(blogList, forKey: "blogs") 
} 
} 

回答

1

这个崩溃也没什么用NSCoder。检入调试器或记录值的值(forKey:“blogList”)。它很可能不存在。你能给出你在网络响应中得到的样本回应吗?

而且这是我的建议,不使用强迫展开,而不是使用可选的后卫作为服务器响应不能被信任,这可能会开始在未来

导致崩溃你应该改变构造下面

init?(id:String, info:[String:AnyObject]){ 
    guard let name = info["blogName"] as? String, let blogStatus1 = info["blogStatus1"] as? String ... so on .. else { 
     return nil 
    } 

    blogName = name 
    . 
    . initialize all field like these 

    // for blog list 
    var tmpBlogList = [BlogList]() 
    if let tmpBlogListInfo = info["blogList"] as? [[String:AnyObject]] 
    { 
     for info in tmpBlogListInfo 
     { 
      let childId = info["blogID"] as? String 
      if let blog = Blog(id:childId, info) { 
        tmpBlogList.append(blog) 
      } 
     } 
    } 
    blogList = tmpBlogList 
} 


//Replace mainArray.append(Blog(blogName: bName, andBlogStatus1: bStatus1, andBlogStatus2: bStatus2, andBlogURL: bURL, andBlogID: bID, andBlogType: bType, andBlogDate: bDate, andBlogPop: bPop, blogList: blogList as! [Blog])) 
if let blog = Blog(id: bID, info: blogList) { 
     mainArray.append(blog) 
} 
+0

所以发生崩溃是因为“blogList”为空?我必须禁用NSCoder来打印出'mainArray',这是网络存储对象的地方。我无法打印出“blogList”,因为它在该行中崩溃。不使用NSCoder打印mainArray。 '这是mainArray []'(缩短它,因为不适合) – BroSimple

+0

我怎样才能防止崩溃? – BroSimple

+1

可以打印的打印( “索引:\(i)中,内容:\(字符串(描述:jsonArray [I]))”)读取blogList之前。 – Atif

相关问题