我一直在寻找一种方法来将Structs保存在内部存储中,直到我在链接中找到一个表单:https://stackoverflow.com/a/40063878/6566615,我尝试使用其他Structs,它可以正常工作,至少是一个可能快速退出我在Structs中存储信息的问题,现在我的新问题是以下结构(CoursesG)有参数,其中一个是另一个Struct。我尝试基于链接中描述的方法以相当结构化的方式进行此操作,但在尝试保存信息时抛出错误。
struct CursosG {
let id: Int
let nrc: String
let profesor: String
let carreras: [Carreras]
let dia: String
let bloque: String
let sala: String
let idcurso: Int
let comentario: String
let curso: String
init(id: Int, nrc: String, profesor: String, carreras: [Carreras], dia: String, bloque: String, sala: String, idcurso: Int, comentario: String, curso: String) {
self.id = id
self.nrc = nrc
self.profesor = profesor
self.carreras = carreras
self.dia = dia
self.bloque = bloque
self.sala = sala
self.idcurso = idcurso
self.comentario = comentario
self.curso = curso
}
struct Carreras {
let id: Int
let nombre: String
let semestre: Int
init(id: Int, nombre: String, semestre: Int) {
self.id = id
self.nombre = nombre
self.semestre = semestre
}
}
}
extension CursosG {
init?(data: NSData) {
if let coding = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as? Encoding {
id = coding.id as Int
nrc = coding.nrc as String
profesor = coding.profesor as String
carreras = coding.carreras as [Carreras]
dia = coding.dia as String
bloque = coding.bloque as String
sala = coding.sala as String
idcurso = coding.idcurso as Int
comentario = coding.comentario as String
curso = coding.curso as String
} else {
return nil
}
}
func encode() -> NSData {
return NSKeyedArchiver.archivedData(withRootObject: Encoding(self)) as NSData
}
private class Encoding: NSObject, NSCoding {
let id: NSInteger
let nrc: NSString
let profesor: NSString
let carreras: [Carreras]
let dia: NSString
let bloque: NSString
let sala: NSString
let idcurso: NSInteger
let comentario: NSString
let curso: NSString
init(_ CursosG: CursosG) {
id = CursosG.id as NSInteger
nrc = CursosG.nrc as NSString
profesor = CursosG.profesor as NSString
carreras = CursosG.carreras as [Carreras]
dia = CursosG.dia as NSString
bloque = CursosG.bloque as NSString
sala = CursosG.sala as NSString
idcurso = CursosG.idcurso as NSInteger
comentario = CursosG.comentario as NSString
curso = CursosG.curso as NSString
}
public required init?(coder aDecoder: NSCoder) {
if let id = aDecoder.decodeObject(forKey: "id") as? NSInteger { self.id = id } else { return nil }
if let nrc = aDecoder.decodeObject(forKey: "nrc") as? NSString { self.nrc = nrc } else { return nil }
if let profesor = aDecoder.decodeObject(forKey: "profesor") as? NSString { self.profesor = profesor } else { return nil }
if let carreras = aDecoder.decodeObject(forKey: "carreras") as? [Carreras] { self.carreras = carreras } else { return nil }
if let dia = aDecoder.decodeObject(forKey: "dia") as? NSString { self.dia = dia } else { return nil }
if let bloque = aDecoder.decodeObject(forKey: "bloque") as? NSString { self.bloque = bloque } else { return nil }
if let sala = aDecoder.decodeObject(forKey: "sala") as? NSString { self.sala = sala } else { return nil }
if let idcurso = aDecoder.decodeObject(forKey: "idcurso") as? NSInteger { self.idcurso = idcurso } else { return nil }
if let comentario = aDecoder.decodeObject(forKey: "comentario") as? NSString { self.comentario = comentario } else { return nil }
if let curso = aDecoder.decodeObject(forKey: "curso") as? NSString { self.curso = curso } else { return nil }
}
public func encode(with aCoder: NSCoder) {
aCoder.encode(id, forKey: "id")
aCoder.encode(nrc, forKey: "nrc")
aCoder.encode(profesor, forKey: "profesor")
aCoder.encode(carreras, forKey: "carreras")
aCoder.encode(dia, forKey: "dia")
aCoder.encode(bloque, forKey: "bloque")
aCoder.encode(sala, forKey: "sala")
aCoder.encode(idcurso, forKey: "idcurso")
aCoder.encode(comentario, forKey: "comentario")
aCoder.encode(curso, forKey: "curso")
}
}
}
extension CursosG.Carreras {
init?(data: NSData) {
if let coding = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as? Encoding {
id = coding.id as Int
nombre = coding.nombre as String
semestre = coding.semestre as Int
} else {
return nil
}
}
func encode() -> NSData {
return NSKeyedArchiver.archivedData(withRootObject: Encoding(self)) as NSData
}
private class Encoding: NSObject, NSCoding {
let id: NSInteger
let nombre: NSString
let semestre: NSInteger
init(_ Carreras: CursosG.Carreras) {
id = Carreras.id as NSInteger
nombre = Carreras.nombre as NSString
semestre = Carreras.semestre as NSInteger
}
public required init?(coder aDecoder: NSCoder) {
if let id = aDecoder.decodeObject(forKey: "id") as? NSInteger { self.id = id } else { return nil }
if let nombre = aDecoder.decodeObject(forKey: "nombre") as? NSString { self.nombre = nombre } else { return nil }
if let semestre = aDecoder.decodeObject(forKey: "semestre") as? NSInteger { self.semestre = semestre } else { return nil }
}
public func encode(with aCoder: NSCoder) {
aCoder.encode(id, forKey: "id")
aCoder.encode(nombre, forKey: "nombre")
aCoder.encode(semestre, forKey: "semestre")
}
}
}
let encoded = CursosAllG.map { $0.encode()}
UserDefaults.standard.set(encoded, forKey: "my-key")
2017-02-11 15:53:27.404 Tongoy UCN[30475:714874] -[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x600000486bd0
2017-02-11 15:53:27.491 Tongoy UCN[30475:714874] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x600000486bd0'
答案 0 :(得分:0)
NSUserDefaults在其可以处理的类型中受到限制:NSData,NSString,NSNumber,NSDate,NSArray和NSDictionary。因此,不能保存Swift对象或结构。必须将其他任何内容转换为NSData对象。
NSUserDefaults与NSArchiver的工作方式不同。由于您已经将NSCoder添加到您的类中,因此您最好的选择可能是使用NSArchiver将其保存并恢复到Documents目录中的文件。
来自Apple NSUserDefaults文档:
默认对象必须是属性列表,即(或 对于集合的实例组合):NSData,NSString, NSNumber,NSDate,NSArray或NSDictionary。如果你想存储任何 在其他类型的对象中,通常应将其存档以创建 NSData的实例。