如何使用swift将自定义结构数组保存到NSUserDefault? [英] How to save an array of custom struct to NSUserDefault with swift?

查看:320
本文介绍了如何使用swift将自定义结构数组保存到NSUserDefault?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为"News"的自定义结构,我想将其附加到NSUserDefault的数组中.但是它显示错误类型'News'不符合协议'AnyObject'".

I have an custom struct called 'News' that I want to append into the array to NSUserDefault. But it's showing error "Type 'News' does not conform to protocol 'AnyObject'".

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

I don't want to change the 'News' struct to a class since it's being used for other code already. Is there anyway that I can change NSUserDefaults.standardUserDefaults().arrayForKey("savedNewsArray") type to [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仅保存很少的类型集:NSDataNSStringNSNumberNSDateNSArray仅包含以下类型类型或NSDictionary仅包含这些类型.因此,最好的选择是使用NSKeyedUnarchiver编码结构,该结构需要一个符合NSCoding的值.您可以使您的类型符合此要求,但我认为将其隐藏于用户中并为内部表示仅提供一个私有类是更清洁的方法,例如:

NSUserDefaults can only save a very small set of types: NSData, NSString, NSNumber, NSDate, NSArray containing only these types, or NSDictionary containing only these types. So your best bet is to encode your struct using an NSKeyedUnarchiver, which required a value that conforms to NSCoding. You could make your type conform to this, but I think it's cleaner to hide that from your users and simply have a private class for the internal representation, like this:

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映射到您的阵列上即可:

Then to save your array you can simply map .encode over your array:

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:

and to get it back you can simply pass the NSData to the init:

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

这篇关于如何使用swift将自定义结构数组保存到NSUserDefault?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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