我试图在xCode 8,Swift 3中保存名为Lokacija(英语:Location)的本地Array of Custom Class。
我尝试使用UserDefault保存它,但不幸的是它不能使用自定义类。所以我找到了这篇文章:http://ioscake.com/how-to-archive-and-unarchive-custom-objects-in-swift-or-how-to-save-custom-object-to-nsuserdefaults-in-swift.html。我尝试了两种解决方案,但它们都没有为我工作。 BTW文章是用Swift 2.x编写的,正如我所说我使用的是Swift 3,所以我不得不翻译它。
我首先尝试了这个:
class Lokacija: NSObject, NSCoding {
var _name : String
var _address : String
var _long : Double
var _lat : Double
init(name : String, address : String, lat : Double, long : Double) {
_name = name
_address = address
_lat = lat
_long = long
//day month year
}
func encode(with aCoder: NSCoder) {
print("ENCODINGGG!!!")
aCoder.encode(_name, forKey: "name")
aCoder.encode(_address, forKey: "address")
aCoder.encode(_long, forKey: "long")
aCoder.encode(_lat, forKey: "lat")
}
}
//in custom .swift "Utils"
static func saveLocations(lokacije: [Lokacija]) {
let dataBlob = NSKeyedArchiver.archivedData(withRootObject: lokacije)
UserDefaults.standard.set(dataBlob, forKey: "lista")
UserDefaults.standard.synchronize()
}
static func loadLocations() -> [Lokacija]? {
guard let decodedDataBlob = UserDefaults.standard.object(forKey: "lista") as? Data, let loadedLocations = NSKeyedUnarchiver.unarchiveObject(with: decodedDataBlob) as? [Lokacija] else {
return nil
}
return loadedLocations
}
//on action
lista.append(selectedLoc)
Utils.saveLocations(lokacije: lista)
//in view did load
if let listaBase = Utils.loadLocations() {
lista = listaBase
self.plannerTable.reloadData()
print(listaBase.count)
print(lista.count)
} else {
print("PATKA MOREEE!!!")
}
问题是它没有在listaBase中写任何东西,它是空的。 然后我尝试了第二个解决方案:
class Lokacija: NSObject, NSCoding {
var _name : String
var _address : String
var _long : Double
var _lat : Double
init(name : String, address : String, lat : Double, long : Double) {
_name = name
_address = address
_lat = lat
_long = long
//day month year
}
func encode(with aCoder: NSCoder) {
print("ENCODINGGG!!!")
aCoder.encode(_name, forKey: "name")
aCoder.encode(_address, forKey: "address")
aCoder.encode(_long, forKey: "long")
aCoder.encode(_lat, forKey: "lat")
}
required convenience init?(coder aDecoder: NSCoder) {
print("DECODEDDD!!!")
guard let unName = aDecoder.decodeObject(forKey: "name") as? String, let unAddress = aDecoder.decodeObject(forKey: "address") as? String, let unLong = aDecoder.decodeObject(forKey: "long") as? Double, let unLat = aDecoder.decodeObject(forKey: "lat") as? Double
else {
return nil
}
self.init(name: unName, address: unAddress, lat: unLat, long: unLong)
}
private class func getFileUrl() -> NSURL {
let documentsDirectory = FileManager().urls(for: (.documentDirectory), in: .userDomainMask).first!
let archiveURL = documentsDirectory.appendingPathComponent("lista")
return archiveURL as NSURL
}
class func saveLocations(locations: [Lokacija]){
let success = NSKeyedArchiver.archiveRootObject(locations, toFile: Lokacija.getFileUrl().path!)
if !success {
print("failed to save")
}
}
class func loadLocations() -> [Lokacija] {
if let locBase = NSKeyedUnarchiver.unarchiveObject(withFile: Lokacija.getFileUrl().path!) as? [Lokacija] {
return locBase
}
print("NIL")
return [Lokacija]()
}
}
//on action
lista.append(selectedLoc)
Lokacija.saveLocations(locations: lista)
//on view did load
if Lokacija.loadLocations() != nil {
let retrivedLocations = Lokacija.loadLocations()
lista = retrivedLocations
self.plannerTable.reloadData()
print(retrivedLocations.count)
print(lista.count)
}
else {
print("FAILL!!!")
}
我遇到了完全相同的问题。
答案 0 :(得分:0)
您解码Double
值的方式存在问题。使用以下代码作为解码初始化程序,它将起作用:
required convenience init?(coder aDecoder: NSCoder) {
print("DECODEDDD!!!")
guard let unName = aDecoder.decodeObject(forKey: "name") as? String, let unAddress = aDecoder.decodeObject(forKey: "address") as? String else {
return nil
}
let unLong = aDecoder.decodeDouble(forKey: "long")
let unLat = aDecoder.decodeDouble(forKey: "lat")
self.init(name: unName, address: unAddress, lat: unLat, long: unLong)
}