Swift:self.init(编码器:aDecoder)正在使用 EXC_BAD_ACCESS 使应用程序崩溃

Swift: self.init (coder : aDecoder) is crashing app with EXC_BAD_ACCESS

使用 NSCoder 和 NSKeyArchiver 时出现应用程序崩溃错误。

我最近做了一个关于 NSCoder 的 post 但从那以后我改变了我的代码并得到了一个新的错误并决定一个新的 post 是最好的。

该应用程序是一个博客 reader,使用 PHP 从 MYSQL 数据库中读取,并使用 Swift 中的自定义对象填充 table 视图JSON。我一直在尝试保存 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 - table 视图所在的位置

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

在我看来就像一个无限循环。你调用 init(coder:),第一行调用 init(coder:),第一行调用 init(coder:),如此循环往复。

您需要在其中调用不同的初始化程序。请尝试 self.init()

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

override init() {
    super.init()
 }