swift2 如何使用swift将自定义结构体的数组保存到NSUserDefault?[duplicate]

yhived7q  于 2022-11-06  发布在  Swift
关注(0)|答案(4)|浏览(216)

此问题在此处已有答案

Save Struct to UserDefaults(9个答案)
四个月前关门了。
我有一个名为“News”的自定义结构,我想将它追加到NSUserDefault的数组中。但它显示错误“类型”News“不符合协议”AnyObject“”。
我不想将“News”结构体更改为类,因为它已经被其他代码使用。是否有任何方法可以将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()

下面是“News”结构。

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
    }
}
xbp102n0

xbp102n01#

NSUserDefaults只能保存非常小的类型集:NSDataNSStringNSNumberNSDateNSArrayNSDictionary。因此,最好的办法是使用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")
        }

    }
}

然后,为了保存数组,只需将.encodeMap到数组上:

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)! }
flvlnr44

flvlnr442#

以下是我所遵循的流程
1.使您的结构对象
1.将struct转换为Json对象(我会给予你文件链接将struct转换为JsonObject和jsonString -〉https://github.com/vijayvir/SwiftApi/blob/master/StructureToJson/StructToJson.swift)将此文件导入到你的项目中:-)
1.将该值追加到数组
1.如果你想保存在用户默认值中,我更喜欢你创建数组的类对象,如下所示,(因为你可以从任何地方访问)
1.按如下所示将阵列保存为用户默认值

要保存的结构

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元素保存到数组此处将结构对象转换为json对象

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 )

:—)

qf9go6mv

qf9go6mv3#

使用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)
xmakbtuz

xmakbtuz4#

我也遇到了同样的问题,上面的答案都不适合我。我终于找到了这个帖子:https://cocoacasts.com/ud-5-how-to-store-a-custom-object-in-user-defaults-in-swift
这简单地解释了如何使用JSON编码来实现它。它的工作原理与帖子中描述的完全一样。

相关问题