Swift:self.init(coder:aDecoder)与EXC_BAD_ACCESS碰撞应用程序

问题描述:

使用NSCoder和NSKeyArchiver时出现错误应用程序崩溃。Swift:self.init(coder:aDecoder)与EXC_BAD_ACCESS碰撞应用程序

enter image description here 我在NSCoder周围发了一篇最近的文章,但自那时起我改变了我的代码,并得到一个新的错误,并决定一个新的帖子是最好的。

该应用程序是一个博客阅读器,从使用PHP在MYSQL数据库中读取以使用JSON在Swift中使用自定义对象填充表视图。我一直试图保存mainArray,以便当用户在单元之间移动单元格时(每个单元都有一个数组),它可以保存用户离开它的位置。

Blog.swift:处理的博客自定义对象

import UIKit 

class Blog: NSObject, NSCoding { 

var blogName: String! 
var blogStatus1: String! 
var blogStatus2: String! 
var blogURL: String! 
var blogID: String! 
var blogType: String! 
var blogDate: String! 
var blogPop: String! 

static func createBlog(from jsonObject: AnyObject) -> Blog? { 

    guard let bID: String = jsonObject.object(forKey: "id") as? String, 
     let bName: String = jsonObject.object(forKey: "blogName") as? String, 
     let bStatus1: String = jsonObject.object(forKey: "blogStatus1") as? String, 
     let bStatus2: String = jsonObject.object(forKey: "blogStatus2") as? String, 
     let bURL: String = jsonObject.object(forKey: "blogURL") as? String, 
     let bType: String = jsonObject.object(forKey: "blogType") as? String, 
     let bDate: String = jsonObject.object(forKey: "blogDate") as? String, 
     let bPop: String = jsonObject.object(forKey: "blogPop") as? String 

     else { 
      print("Error: (Creating Blog Object)") 
      return nil 
} 

let blog = Blog() 
    blog.blogName = bName 
    blog.blogStatus1 = bStatus1 
    blog.blogStatus2 = bStatus2 
    blog.blogURL = bURL 
    blog.blogID = bID 
    blog.blogType = bType 
    blog.blogDate = bDate 
    blog.blogPop = bPop 
    return blog 
} 

// NSCoding 
convenience required init?(coder aDecoder: NSCoder) { 
    self.init (coder : aDecoder) // *** Crashes Here *** 
    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 
} 

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") 
} 
} 

MainController.swift - 如果表视图位于

var mainArray = [Blog]() 
var followedArray = [Blog]() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    // Receiving Data from Server 
    retrieveData() 

    if let data = UserDefaults.standard.data(forKey: "mainArrayKey"), 
     let myBlogList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Blog] { 
     mainArray = myBlogList 
     print("mainArray: \(mainArray)") 
    } else { 
     print("Error: (Saving to UserDefaults)") 
    } 
} 

// Retrieving Data from Server 
func retrieveData() { 

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

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

     // Looping through jsonArray 
     for jsonObject in jsonArray { 
      if let blog = Blog.createBlog(from: jsonObject as AnyObject) { 
       mainArray.append(blog) 

       // Save to UserDefaults 
       let encodedData = NSKeyedArchiver.archivedData(withRootObject: mainArray) 
       UserDefaults.standard.set(encodedData, forKey: "mainArrayKey") 
      } 
     } 
    } 
    catch { 
     print("Error: (Retrieving Data)") 
    } 
    myTableView.reloadData() 

    // Logs 
    print("This is mainArray", mainArray) 

    // Check UserDefaults 
    if UserDefaults.standard.object(forKey: "mainArrayKey") != nil{ 
     print("mainArray key exists") 
    } 
    else { 
     print("mainArray key does not exist") 
    } 
} 
+0

你想写'super.init'吗? 'self.init'好像是一个无限循环。 – luk2302

+0

我知道EXC_BAD_ACCESS是内存管理。这是因为它是一个无限循环吗?我如何申请super.init? – BroSimple

+1

要么删除初始化调用,要么简单地用自己的super替换该行 – luk2302

看起来像一个无限循环给我。您拨打init(coder:),第一行呼叫init(coder:),第一行呼叫init(coder:),等等无限。

你需要调用其中的一个不同的初始化器。改为尝试self.init()

+1

它的工作!就像你说的,必须从'self.init()'中删除'coder:aDecoder'。 – BroSimple

正如其他人所说,这确实是一个无限循环。你需要做的是将其更改为self.init(),并将以下代码添加到代码中。或者实现你自己的init来完成任何需要完成的任务。

override init() { 
    super.init() 
}