Swift:在NSKeyedArchiver错误

Swift 3 iOS 10,尝试在NSKeyedArchiver中保存自定义对象的数组,基本上是在用户使用button切换部分之后保存表视图。 我已经尝试了几个post来解决这个问题,但没有运气,现在我试图自己做NSCoding和NSKeyedArchiver。

错误:

无法将types“[Blog]”的值转换为期望的参数types“NSCoder”

错误代码在Blog.swift中,处理NSCoding和我的博客对象的代码

import UIKit class BlogsCoding: NSObject, NSCoding { var blogList : [Blog] init(blogList : [Blog]) { self.blogList = blogList } convenience required init?(coder aDecoder: NSCoder) { guard let blogList = aDecoder.decodeObject(forKey: "blogs") as? [Blog] else { return nil } self.init (blogList : blogList) } func encode(with aCoder: NSCoder) { aCoder.encode(blogList, forKey: "blogs") } } class Blog: NSObject, NSCoding { // To conform to 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] // To conform to NSCoding override init() { } // 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 conform to NSCoding { super.init() 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 // To conform to NSCoding } // To conform to NSCoding convenience required init?(coder aDecoder: NSCoder) { guard let blogList = aDecoder.decodeObject(forKey: "blogs") as? [Blog] else { return nil } self.init (coder : blogList) // *---* Error is here *---* } func encode(with aCoder: NSCoder) { aCoder.encode(blogList, forKey: "blogs") } } 

在MainController.swift – 我的tableview在哪里

 override func viewDidLoad() { var path : String { let manager = FileManager.default let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL return url.appendingPathComponent("blogs")!.path // I have a blogs.plist for this, doing it right? } } 

button

 // Follow Button @IBAction func followButtonClick(_ sender: UIButton!) { // After Updating Table, Save Arrays var success = false // mainArray is array holding custom objects from json success = NSKeyedArchiver.archiveRootObject(mainArray, toFile: "path") // If I dont use "" I get undeclared 'path' if success { print("Saved Blogs") } else { print("Didn't Save Blogs") } } 

从服务器接收数据

 // Retrieving Data from Server func retrieveData() { let getDataURL = "http://blogexample.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 // New 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 let blogList: NSObject = ((jsonArray[i]) as! NSObject).value(forKey: "blogList") as! NSObject // Add Blog Objects to Main Array 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)") } 

另外,是“path”定义和使用的权利? 谢谢!

NSCoding的目的是将类的每个属性转换为符合属性列表的格式。

首先声明所有的String属性为非可选的,因为自定义初始化程序只传递非可选参数。

然后在init(coder添加行init(coderencode(with方法( 编辑

 class Blog: NSObject, NSCoding { // To conform to 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] // To conform to 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 conform 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 // To conform to NSCoding super.init() } // To conform to NSCoding convenience required init?(coder aDecoder: NSCoder) { 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] super.init (coder : aDecoder) } 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") } } 

但是有一个潜在的警告:

编码/解码目标类的对象数组可能会导致意外行为,例如无限循环。 考虑一下。 您可能需要单独编码数组。


第二个问题是一个错字,你把"path"作为一个string而不是一个可变的path

 NSKeyedArchiver.archiveRootObject(mainArray, toFile: path)