我有一个名为' News'的自定义结构。我想将数据附加到NSUserDefault。但它显示错误" Type' News'不符合协议' AnyObject'"。
我不想改变'新闻' struct to a class,因为它已经用于其他代码。无论如何我可以将NSUserDefaults.standardUserDefaults()。arrayForKey(" savedNewsArray")类型更改为[新闻]?
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
}
}
答案 0 :(得分:14)
NSUserDefaults只能保存一小组类型:NSString
,NSNumber
,NSDate
,NSArray
,NSDictionary
仅包含这些类型,或{ {1}}仅包含这些类型。因此,最好的办法是使用NSKeyedUnarchiver对结构进行编码,这需要一个符合NSCoding的值。你可以让你的类型符合这一点,但我认为从你的用户隐藏它并且只是为内部表示创建一个私有类更清晰,如下所示:
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)! }
答案 1 :(得分:3)
以下是我遵循的流程
如果你想保存在用户默认值中,我更喜欢你制作数组的类对象,如下所示(你可以从任何地方访问)
将数组保存为用户默认值,如下所示
要保存的结构
struct CardDetails : StructJSONSerializable { var emailId :String var accountNo : String var expDate : String var cvc : String var isCurrrent : Bool = false init(card : Dictionary<String, Any> ) { emailId = card["emailId"]! as! String accountNo = card["accountNo"]! as! String expDate = card["expDate"]! as! String cvc = card["cvc"]! as! String isCurrrent = card["isCurrrent"]! as! Bool } }
将数组保存为用户默认
class var cards : [AnyObject] { get { if (UserDefaults.standard.object(forKey:"cardss") != nil) { if let data = UserDefaults.standard.object(forKey: "cardss") as? Data { let unarc = NSKeyedUnarchiver(forReadingWith: data) let newBlog = unarc.decodeObject(forKey: "root") return newBlog as! [AnyObject] } else { return [] } } else { return [] } } set { //print(type(of: newValue) , newValue) let archiveData = NSKeyedArchiver.archivedData(withRootObject: newValue) let ud = UserDefaults.standard ud.set( archiveData ,forKey: "cardss") ud.synchronize() } }
如何将Struct元素保存到数组 这里将struct对象转换为json Object
let firstCard = CardDetails(emailId: "asdf", accountNo: "dada", expDate: "nvn", cvc: "e464w", isCurrrent: true) CardsViewController.cards.append(firstCard.toJsonObect())
如何从数组访问对象 这里将json Object对象转换为Struct
let sameCardIs = CardDetails(card: CardsViewController.cards.last as! Dictionary<String, Any>) print ("Element Function " , sameCardIs )
:-)
答案 2 :(得分:0)
在SWIFT 3中工作
按照与ahruss类似的方法,我最终以下列方式实现:
struct MyObject {
var foo : String
var bar : String?
}
extension MyObject {
init?(data: NSData) {
if let coding = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as? Encoding {
foo = coding.foo as String
bar = coding.bar as String?
} else {
return nil
}
}
func encode() -> NSData {
return NSKeyedArchiver.archivedData(withRootObject: Encoding(self)) as NSData
}
private class Encoding: NSObject, NSCoding {
let foo : NSString
let bar : NSString?
init(_ myObject: MyObject) {
foo = myObject.foo
bar = myObject.bar
}
@objc required init?(coder aDecoder: NSCoder) {
if let foo = aDecoder.decodeObject(forKey: "foo") as? NSString {
self.foo = foo
} else {
return nil
}
bar = aDecoder.decodeObject(forKey: "bar") as? NSString
}
@objc func encode(with aCoder: NSCoder) {
aCoder.encode(foo, forKey: "foo")
aCoder.encode(bar, forKey: "bar")
}
}
}
哦,使用它只需键入以下内容:
let myObject = MyObject(foo: "foo", bar: "bar")
UserDefaults.standard.set(myObject.encode(), forKey: "test")
要获取它,
let objectData = UserDefaults.standard.object(forKey: "test") as? Data?
guard let storedObject = objectData else {
return
}
let fetchedObject: MyObject = MyObject(data: storedObject as NSData)