使用 aCoder 编码时出现 Swift PFFile 异常

Posted

技术标签:

【中文标题】使用 aCoder 编码时出现 Swift PFFile 异常【英文标题】:Swift PFFile Exception when encoding with aCoder 【发布时间】:2017-08-30 18:28:01 【问题描述】:

我正在尝试对 PFFile 进行编码并永久保存它,但它返回异常:

班级:

import UIKit

import Parse

class Usuario: PFObject, PFSubclassing, NSCoding 

    //MARK: Propriedades
    //O NSManaged é para o PFObject
    @NSManaged var nome: String?
    @NSManaged var foto: PFFile?
    @NSManaged var dataNascimento: Date?
    @NSManaged var numeroTelefone: String?
    @NSManaged var pais: PaisCodigo?
    @NSManaged var telefoneE164: String?

    static func parseClassName() -> String 
        return "Usuario"
    


    //Isto é para NSObject e NSCoding
    override init() 

        super.init()
    

    required init(coder aDecoder: NSCoder) 

        super.init()

        self.nome = aDecoder.decodeObject(forKey: "nome") as? String
        self.foto = aDecoder.decodeObject(forKey: "foto") as? PFFile
        self.dataNascimento = aDecoder.decodeObject(forKey: "dataNascimento") as? Date
        self.numeroTelefone = aDecoder.decodeObject(forKey: "numeroTelefone") as? String
        self.pais = aDecoder.decodeObject(forKey: "pais") as? PaisCodigo
        self.telefoneE164 = aDecoder.decodeObject(forKey: "telefoneE164") as? String
    

    func encode(with aCoder: NSCoder) 

        if let nomeUsuario = nome 
            aCoder.encode(nomeUsuario, forKey: "nome")
        

        if let fotoUsuario = foto 
            //The problems happens here
            aCoder.encode(fotoUsuario, forKey: "foto")
        

        if let dataNascimentoUsuario = dataNascimento 
            aCoder.encode(dataNascimentoUsuario, forKey: "dataNascimento")
        

        if let numeroTelefoneUsuario = numeroTelefone 
            aCoder.encode(numeroTelefoneUsuario, forKey: "numeroTelefone")
        

        if let paisUsuario = pais 
            aCoder.encode(paisUsuario, forKey: "pais")
        

        if let telefoneE164Usuario = telefoneE164 
            aCoder.encode(telefoneE164Usuario, forKey: "telefoneE164")
        
    

我尝试用这种方法保存数据:

contatos 对象是 Usuario(上面的类)的数组

func fazerCacheContatos() 

        let userDefaults = UserDefaults.standard

        let contatosIDoPartyCodificados: Data = NSKeyedArchiver.archivedData(withRootObject: contatos)

        userDefaults.set(contatosCodificados, forKey: "cacheContatos")

        userDefaults.synchronize()
    

当我运行应用程序时,我收到此异常:

-[PFFile encodeWithCoder:]: unrecognized selector sent to instance 0x170e513d0

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PFFile encodeWithCoder:]: unrecognized selector sent to instance 0x170e513d0'

【问题讨论】:

【参考方案1】:

您的PFFile 类似乎不支持NSCoding 协议。如果PFFile 是你自己的类,那么你可以通过添加NSCoding 支持来解决这个问题。如果PFFile 是您从没有源代码的第三方获得的类,那么您将不得不找到其他方法来存储稍后重构PFFile 所需的信息。

【讨论】:

感谢您的建议。【参考方案2】:

解决方案是将对象转换为 UIImage 进行编码和解码后转换为 PFFile,如下代码:

import UIKit

import Parse

class Usuario: PFObject, PFSubclassing, NSCoding 

    //MARK: Propriedades
    //O NSManaged é para o PFObject
    @NSManaged var nome: String?
    @NSManaged var foto: PFFile?
    @NSManaged var dataNascimento: Date?
    @NSManaged var numeroTelefone: String?
    @NSManaged var pais: PaisCodigo?
    @NSManaged var telefoneE164: String?

    static func parseClassName() -> String 
        return "Usuario"
    


    //Isto é para NSObject e NSCoding
    override init() 

        super.init()
    

    required init(coder aDecoder: NSCoder) 

        super.init()

        self.nome = aDecoder.decodeObject(forKey: "nome") as? String

        let image = aDecoder.decodeObject(forKey: "foto") as? UIImage
        if let fotoImage = image 
            self.foto = PFFile(data: UIImagePNGRepresentation(fotoImage)!)
        

        self.dataNascimento = aDecoder.decodeObject(forKey: "dataNascimento") as? Date
        self.numeroTelefone = aDecoder.decodeObject(forKey: "numeroTelefone") as? String
        self.pais = aDecoder.decodeObject(forKey: "pais") as? PaisCodigo
        self.telefoneE164 = aDecoder.decodeObject(forKey: "telefoneE164") as? String
    

    func encode(with aCoder: NSCoder) 

        if let nomeUsuario = nome 
            aCoder.encode(nomeUsuario, forKey: "nome")
        

        if let fotoUsuario = foto 
            do 
                let dataImage = try fotoUsuario.getData()

                let image = UIImage(data: dataImage)!

                aCoder.encode(image, forKey: "foto")
             catch 
                //Erro
            
        

        if let dataNascimentoUsuario = dataNascimento 
            aCoder.encode(dataNascimentoUsuario, forKey: "dataNascimento")
        

        if let numeroTelefoneUsuario = numeroTelefone 
            aCoder.encode(numeroTelefoneUsuario, forKey: "numeroTelefone")
        

        if let paisUsuario = pais 
            aCoder.encode(paisUsuario, forKey: "pais")
        

        if let telefoneE164Usuario = telefoneE164 
            aCoder.encode(telefoneE164Usuario, forKey: "telefoneE164")
        
    

【讨论】:

以上是关于使用 aCoder 编码时出现 Swift PFFile 异常的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 Swift 从 Parse 显示图像时出现问题

使用 Alamofire 和 PromiseKit 使用 Swift 时出现 Void 错误(请求)

使用 performSegueWithIdentifier 时出现 Swift UIImageView 错误

在 XCode/Swift 上安装/使用 DCKit 时出现问题

使用 objc_getAssociatedObject() 时出现奇怪的 Swift 行为

使用 NSCoding Swift 保存对象时出现异常