Swift:NSKeyedArchiver 中的错误 [英] Swift: Error in NSKeyedArchiver

查看:62
本文介绍了Swift:NSKeyedArchiver 中的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Swift 3 iOS 10, Trying to save array with custom objects in NSKeyedArchiver, basically trying to save the table view after the user uses the buttons to switch between sections. I've tried several post to solve the issue but no luck, now I'm trying to do it myself NSCoding and NSKeyedArchiver.

错误:

无法将类型[Blog]"的值转换为预期的参数类型NSCoder"

Cannot convert value of type '[Blog]' to expected argument type 'NSCoder'

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

Error is in code in Blog.swift, Code that handles NSCoding and my Blog Objects

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 在哪里

In MainController.swift - Where my tableview is

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

此外,路径"的定义和使用是否正确?谢谢!

Also, is 'path' defined and used right? Thank you!

推荐答案

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

The purpose of NSCoding is to convert each single property of the class to a property list compliant format.

首先将所有 String 属性声明为非可选属性,因为自定义初始值设定项仅传递非可选参数.

First of all declare all String properties as non-optional because the custom initializer passes only non-optional parameters.

然后在init(coderencode(with方法(edited)

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

但是有一个潜在的警告:

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

Encoding / decoding an array of objects of the target class may cause unexpected behavior for example an infinite loop. Consider that. You might encode the array separately.

第二个问题是拼写错误,您将 "path" 作为文字字符串而不是变量 path 传递:

The second issue is a typo, you pass "path" as a literal string rather than a variable path:

NSKeyedArchiver.archiveRootObject(mainArray, toFile: path)

这篇关于Swift:NSKeyedArchiver 中的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆