繁体   English   中英

将结构保存到NSUserDefaults中的另一个结构中

[英]Save Struct into another Struct in NSUserDefaults

我一直在寻找一种将Structs保存在内部存储中的方法,直到我在链接中找到一个表单: https : //stackoverflow.com/a/40063878/6566615 ,我尝试使用其他拥有的Structs使其正常工作,至少可以快速退出我在Structs中存储信息的问题,现在我的新问题是以下结构(CoursesG)具有参数,其中一个是另一个Struct。 我尝试根据链接中描述的方法以相当结构化的方式进行操作,但是在尝试保存信息时抛出错误。


结构CursosG和Carreras(在CursosG中)

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

CursosG和Carreras扩展

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' 

NSUserDefaults可以处理的类型受到限制:NSData,NSString,NSNumber,NSDate,NSArray和NSDictionary。 因此,无法保存任何Swift对象或结构。 任何其他内容都必须转换为NSData对象。

NSUserDefaults与NSArchiver的工作方式不同。 由于您已经将NSCoder添加到了类中,所以最好的选择是使用NSArchiver保存并还原到Documents目录中的文件。

从Apple NSUserDefaults文档中:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM