Swift: ошибка в NSKeyedArchiver
Swift 3 iOS 10, пытаясь сохранить массив с пользовательскими объектами в NSKeyedArchiver, в основном пытаясь сохранить табличное представление после того, как пользователь использует кнопки для переключения между разделами. Я пробовал несколько сообщений, чтобы решить эту проблему, но не повезло, теперь я пытаюсь сделать это сам NSCoding и NSKeyedArchiver.
Ошибка:
Невозможно преобразовать значение типа '[Blog]' в ожидаемый тип аргумента '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 - где мой вид таблицы
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?
}
}
Кнопка Follow
// 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)")
}
Кроме того, "путь" определен и используется правильно? Спасибо!
1 ответ
Цель NSCoding
заключается в преобразовании каждого отдельного свойства класса в совместимый формат списка свойств.
Прежде всего объявить все String
свойства не являются необязательными, поскольку пользовательский инициализатор передает только необязательные параметры.
Затем добавьте строки в init(coder
а также encode(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"
как буквенная строка, а не переменная path
:
NSKeyedArchiver.archiveRootObject(mainArray, toFile: path)