arrays - 如何使用 swift 将自定义结构数组保存到 NSUserDefault?

标签 arrays swift struct swift2 nsuserdefaults

<分区>

我有一个名为“News”的自定义结构,我想将其附加到 NSUserDefault 的数组中。但它显示错误“类型‘新闻’不符合协议(protocol)‘AnyObject’”。

我不想将“新闻”结构更改为一个类,因为它已经被其他代码使用了。无论如何,我可以将 NSUserDefaults.standardUserDefaults().arrayForKey("savedNewsArray") 类型更改为 [News] 吗?

var savedNews = NSUserDefaults.standardUserDefaults().arrayForKey("savedNewsArray")
var addSavedNews = savedNews as? [News]
addSavedNews.append(News(id: "00", title: newsTitle, source: source, imageURL: imageURL, url: url))
NSUserDefaults.standardUserDefaults().setObject(addSavedNews, forKey: "savedNewsArray")
NSUserDefaults.standardUserDefaults().synchronize()

这是“新闻”结构。

public struct News {
    public var id: String
    public var title: String
    public var source: String?
    public var imageURL: String?
    public var date: NSDate?
    public var url: String

    init(id: String, title: String, source: String, imageURL: String, url: String) {
        self.id = id
        self.title = title
        self.source = source
        self.imageURL = imageURL
        self.url = url
    }
}

最佳答案

NSUserDefaults 只能保存非常小的一组类型:NSData, NSString, NSNumber, NSDate, NSArray 仅包含这些类型,或 NSDictionary 仅包含这些类型。所以你最好的选择是使用 NSKeyedUnarchiver 对你的结构进行编码,这需要一个符合 NSCoding 的值。您可以使您的类型符合这一点,但我认为向您的用户隐藏它并简单地为内部表示提供一个私有(private)类会更清晰,如下所示:

struct Foo {
    var a : String
    var b : String?
}

extension Foo {
    init?(data: NSData) {
        if let coding = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? Encoding {
            a = coding.a as String
            b = coding.b as String?
        } else {
            return nil
        }
    }

    func encode() -> NSData {
        return NSKeyedArchiver.archivedDataWithRootObject(Encoding(self))
    }

    private class Encoding: NSObject, NSCoding {
        let a : NSString
        let b : NSString?

        init(_ foo: Foo) {
            a = foo.a
            b = foo.b
        }

        @objc required init?(coder aDecoder: NSCoder) {
            if let a = aDecoder.decodeObjectForKey("a") as? NSString {
                self.a = a
            } else {
                return nil
            }
            b = aDecoder.decodeObjectForKey("b") as? NSString
        }

        @objc func encodeWithCoder(aCoder: NSCoder) {
            aCoder.encodeObject(a, forKey: "a")
            aCoder.encodeObject(b, forKey: "b")
        }

    }
}

然后为了保存你的数组,你可以简单地将 .encode 映射到你的数组上:

let fooArray = [ Foo(a: "a", b: "b"), Foo(a: "c", b: nil) ]
let encoded = fooArray.map { $0.encode() }
NSUserDefaults.standardUserDefaults().setObject(encoded, forKey: "my-key")

要取回它,您只需将 NSData 传递给 init:

let dataArray = NSUserDefaults.standardUserDefaults().objectForKey("my-key") as! [NSData]
let savedFoo = dataArray.map { Foo(data: $0)! }

关于arrays - 如何使用 swift 将自定义结构数组保存到 NSUserDefault?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38406457/

相关文章:

struct - Julia:跨不同结构实例的字段应用函数

c - 在 C 中将字符与表指针交换

ios - 如何从父ViewController中的ContainerView获取值?

swift - 为什么在将 8 位二进制值分配给 Int8 类型的 var 时,Swift 语言会发生溢出?

ios - Collection View 单元格大小取决于 UITextView

c - 增加意外错误

c++ - 使用结构时,表达式必须具有(指针到)函数类型

javascript - 在javascript中使用过滤器时获取项目索引

C++。将二维指针数组传递到函数时遇到问题

javascript - 创建多个具有相同值的索引 - 简写