我有一个名为“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)! }