2016-11-24 63 views
1

作为面向协议的编程概念,我创建了我的模型Struct保存具有NSKeyedArchiver和Userdefault的结构数组,其中对象符合NSCoding

我想将“Struct”的数组保存到Userdefault中。但是我在这个模型的数组的编码/解码中遇到问题。

这里是我的模型结构

struct Room { 
    let name : String 
    let id : String 
    let booked : Bool 
} 

在这里,我创建了一个扩展这样

extension Room { 


func decode() -> Room? { 
    let userClassObject = NSKeyedUnarchiver.unarchiveObject(withFile: RoomClass.path()) as? RoomClass 
    return userClassObject?.room 
} 

func encode() { 
    let personClassObject = RoomClass(room: self) 
    NSKeyedArchiver.archiveRootObject(personClassObject, toFile: RoomClass.path()) 
} 

class RoomClass: NSObject, NSCoding { 

    var room : Room? 

    init(room: Room) { 
     self.room = room 
     super.init() 
    } 

    class func path() -> String { 
     let documentsPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first 
     let path = documentsPath?.appending(("/Room")) 
     return path! 
    } 

    func encode(with aCoder: NSCoder) { 
     aCoder.encode(room!.name, forKey: "name") 
     aCoder.encode(room!.id, forKey: "Id") 
     aCoder.encode(room!.booked, forKey: "booked") 
    } 

    required init?(coder aDecoder: NSCoder) { 
     let _name = aDecoder.decodeObject(forKey: "name") as? String 
     let _id = aDecoder.decodeObject(forKey: "Id") as? String 
     let _booked = aDecoder.decodeBool(forKey: "booked") 

     room = Room(name: _name!, id: _id!, booked: _booked) 

     super.init() 
    } 
} 
} 

当我试图挽救arrRoomList(房间对象的数组)像这样

 self.saveRooms(arrayRooms: arrRoomList) 

我得到这个错误

[_SwiftValue encodeWithCoder:]:无法识别的选择发送到实例

我也试图编码每一个对象,然后再尝试将它们保存在默认情况下,随后也它给出了一个错误。

任何人都可以请指导我如何编码/解码结构在Userdefaults数组以正确的方式,而无需将其转换为字典?

+0

看起来很复杂,你在你的结构转换为类编码并保存? – Tj3n

+1

@Idan:我有更多的细节修改我的问题。我想保存结构为默认对象确认NSCoding – Wolverine

+0

转储NSCoding和东西,只需将您的对象转换为字典,然后保存它,非常容易,代码量也类似 – Tj3n

回答

1

您可以尝试型号一样

class CardModel: NSObject 
{ 
    let name : String 
    let id : String 
    let booked : Bool 

    override init() 
    { 
     self.name = "" 
     self.id = "" 
     self.booked = false 
    } 

    required init(coder aDecoder: NSCoder) 
    { 
     self.name = aDecoder.decodeObject(forKey: "name") as! String 
     self.id = aDecoder.decodeObject(forKey: "id") as! String 
     self.booked = aDecoder.decodeObject(forKey: "booked") as! Bool 
    } 

    func encodeWithCoder(_ aCoder: NSCoder) 
    { 
     aCoder.encode(name, forKey: "name") 
     aCoder.encode(id, forKey: "id") 
     aCoder.encode(booked, forKey: "booked") 
    } 
} 

使用由创建CardModel模型对象按对象

let objCardModel = CardModel() 
objCardModel.name = "Shrikant" 
objCardModel.id = "8" 
objCardModel.booked = true 

访问

let userName = objCardModel.name 
+0

是的,但是作为面向协议的编程概念,我用Struct创建了我的模型。我知道我可以通过只创建类来实现这一点。无论如何,我们可以为Struct做到这一点吗? – Wolverine

+0

默认对象必须是属性列表,即,(或用于集合实例组合的实例)属性列表:NSData,NSString,NSNumber,NSDate,NSArray或NSDictionary。如果你想存储任何其他类型的对象,你通常应该将其存档以创建一个NSData实例。 –

+1

这些数据在哪里以及如何保存和检索? – Confused

3

你可以设置的结构直接使用NSKeyedArchiver这样:

struct Room { 
    let name : String 
    let id : String 
    let booked : Bool 
} 

extension Room { 
    func encode() -> Data { 
     let data = NSMutableData() 
     let archiver = NSKeyedArchiver(forWritingWith: data) 
     archiver.encode(name, forKey: "name") 
     archiver.encode(id, forKey: "id") 
     archiver.encode(booked, forKey: "booked") 
     archiver.finishEncoding() 
     return data as Data 
    } 

    init?(data: Data) { 
     let unarchiver = NSKeyedUnarchiver(forReadingWith: data) 
     defer { 
      unarchiver.finishDecoding() 
     } 
     guard let name = unarchiver.decodeObject(forKey: "name") as? String else { return nil } 
     guard let id = unarchiver.decodeObject(forKey: "id") as? String else { return nil } 
     booked = unarchiver.decodeBool(forKey: "booked") 
     self.name = name 
     self.id = id 
    } 
} 

与UserDefaults使用,这样调用:

// to encode to data and save to user defaults 
let room = Room(name: "asdf", id: "123", booked: true) 
UserDefaults.standard.set(room.encode(), forKey: "room") 

// to retrieve from user defaults 
if let data = UserDefaults.standard.object(forKey: "room") as? Data { 
    let room = Room(data: data) 
} 

可以保存/恢复室的一个这样的数组:

func saveRooms(arrayRooms: [Room]) { 
    let roomsData = arrayRooms.map { $0.encode() } 
    UserDefaults.standard.set(roomsData, forKey: "rooms") 
} 

func getRooms() -> [Room]? { 
    guard let roomsData = UserDefaults.standard.object(forKey: "rooms") as? [Data] else { return nil } 
    return roomsData.flatMap { return Room(data: $0) } 
} 


// save 2 rooms to user defaults 
let roomA = Room(name: "A", id: "123", booked: true) 
let roomB = Room(name: "B", id: "asdf", booked: false) 
saveRooms(arrayRooms: [roomA, roomB]) 

// get the rooms 
print(getRooms())