2016-11-24 59 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())