Swift: self.init (coder : aDecoder) 正在使用 EXC_BAD_ACCESS 使应用程序崩溃
Posted
技术标签:
【中文标题】Swift: self.init (coder : aDecoder) 正在使用 EXC_BAD_ACCESS 使应用程序崩溃【英文标题】:Swift: self.init (coder : aDecoder) is crashing app with EXC_BAD_ACCESS 【发布时间】:2017-06-13 20:49:31 【问题描述】:错误是使用 NSCoder 和 NSKeyArchiver 时应用程序崩溃。
我最近发表了一篇关于 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")
【问题讨论】:
你想写super.init
吗? self.init
似乎是一个无限循环。
我知道 EXC_BAD_ACCESS 是内存管理。难道是因为它是一个无限循环?如何申请 super.init?
要么放弃初始化调用,要么在该行中用 super 替换 self
我将其替换为 super.init 但我收到错误消息“传递给不带参数的调用的参数”
请将代码和错误添加为 文本 (using code formatting),而不是图像。图片:A)不允许我们复制和粘贴代码/错误进行测试; B) 不允许根据代码/错误内容进行搜索; C)many more reasons)。通常,文本格式的代码/错误 >>> 图像形式的代码/错误 >>>;没有。除了代码格式的文本之外,只有在图像添加了一些重要的东西,而不仅仅是文本代码/错误时,才应该使用图像。
【参考方案1】:
在我看来就像一个无限循环。你调用init(coder:)
,第一行调用init(coder:)
,第一行调用init(coder:)
,以此类推。
您需要在其中调用不同的初始化程序。请改用self.init()
。
【讨论】:
它正在工作!只需要像你说的那样从'self.init()'中删除'coder:aDecoder'。【参考方案2】:正如其他人所说,这确实是一个无限循环。您需要做的是将其更改为 self.init() 并将以下内容添加到您的代码中。或者实现你自己的 init 来做任何需要做的事情。
override init()
super.init()
【讨论】:
以上是关于Swift: self.init (coder : aDecoder) 正在使用 EXC_BAD_ACCESS 使应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 为啥在 AFHTTPSessionManager 中需要 init(coder)?
Swift:错误:'必需'初始化程序'init(coder :)'必须由'UIView'的子类提供