You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift使用Codable类从Firebase按ID查询文档报错求助

问题描述

我尝试通过文档ID(用户邮箱)从Firebase Firestore查询用户文档,并映射到自定义Codable类Usuario,但一直收到错误:The data couldn’t be read because it is missing.,以下是相关代码和信息,求排查解决。

Firebase数据库结构

集合Usuarios下的文档ID为用户邮箱,文档包含字段:nombre、apellidos、telefono、contraseña、fotoPerfil(可选)、ciudad

Usuario类代码

import Foundation
import FirebaseFirestoreSwift

class Usuario: Codable {
    @DocumentID var email: String?
    let nombre: String
    let apellidos: String
    let telefono: String
    let contraseña: String
    let fotoPerfil: String?
    let ciudad: String
    
    init ( nombre: String, apellidos: String, usuario: String, contraseña: String, fotoPerfil: String?, ciudad: String){
        self.nombre = nombre
        self.apellidos = apellidos
        self.telefono = usuario
        self.contraseña = contraseña
        self.fotoPerfil = nil
        self.ciudad = ciudad
    }
}

查询函数代码

private func buscarUsuarioPorEmail( documentId: String) {
  let docRef = db.collection("Usuarios").document("lorenzorubiorivera@hotmail.com")
  print("This is a quick check for debugging:  \(documentId)")
  docRef.getDocument(as: Usuario.self) { result in
    switch result {
    case .success(let usuario):
      self.usuarioActual = usuario
        print("El usuario actual es: \(self.usuarioActual.nombre) ")
        print(result)
    case .failure(let error):
      print("ERROR ENCONTRADO USUARIO \(error.localizedDescription)")
    }
  }
}

主视图控制器代码

import UIKit
import FirebaseAuth
import FirebaseCore
import FirebaseAnalytics
import FirebaseFirestore
import Lottie

class InicioViewController: UIViewController {
    // He utilizado una variable tipo lazy para poder inicializarla más tarde cuando se llama a la base datos
    lazy var usuarioActual = Usuario()
    lazy var usersCollection = Firestore.firestore().collection("Usuarios")
    @IBOutlet weak var txtEmailUsuario: UITextView!
    // Creamos una conexión a Firestore
    private let db = Firestore.firestore()
    lazy var collectioRef = db.collection("Usuarios")
    
    // MARK: -- Recupero el email mediante su clave en UserDefaults
    private let email = UserDefaults.standard.string(forKey: "emailAutentificado")
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Datos usuario actual"
        txtEmailUsuario.text = email
        buscarUsuarioPorEmail(documentId: email!)
}

控制台输出

This is a quick check for debugging:  lorenzorubiorivera@hotmail.com
ERROR ENCONTRADO USUARIO The data couldn’t be read because it is missing.

问题排查与修复

1. 初始化器参数不匹配且硬设可选字段值

Usuario的初始化器参数usuario被错误赋值给telefono,同时硬把fotoPerfil设为nil,如果Firestore文档中存在fotoPerfil字段,会导致解码时字段不匹配;且参数名和类属性名对应混乱,影响Codable解析。

修复后的初始化器:

init(nombre: String, apellidos: String, telefono: String, contraseña: String, fotoPerfil: String?, ciudad: String) {
    self.nombre = nombre
    self.apellidos = apellidos
    self.telefono = telefono
    self.contraseña = contraseña
    self.fotoPerfil = fotoPerfil // 使用传入的参数,而非硬设为nil
    self.ciudad = ciudad
}

2. 查询函数硬编码文档ID

buscarUsuarioPorEmail中直接写死文档ID,未使用传入的documentId参数,导致无法动态查询目标用户,甚至如果硬编码的文档不存在就会触发错误。

修复后的查询函数:

private func buscarUsuarioPorEmail(documentId: String) {
    let docRef = db.collection("Usuarios").document(documentId) // 使用传入的documentId参数
    print("This is a quick check for debugging:  \(documentId)")
    docRef.getDocument(as: Usuario.self) { result in
        switch result {
        case .success(let usuario):
            self.usuarioActual = usuario
            print("El usuario actual es: \(usuario.nombre) ")
        case .failure(let error):
            print("ERROR ENCONTRADO USUARIO \(error.localizedDescription)")
            // 额外调试:检查文档是否存在
            docRef.getDocument { snapshot, err in
                if let err = err {
                    print("获取文档快照失败:\(err)")
                } else if snapshot?.exists == false {
                    print("文档不存在:\(documentId)")
                }
            }
        }
    }
}

3. usuarioActual初始化错误

lazy var usuarioActual = Usuario()会尝试调用默认初始化器,但Usuario没有默认初始化逻辑(所有非可选属性无默认值),会导致编译或运行时异常。

修复后的变量声明:

var usuarioActual: Usuario? // 声明为可选类型,避免提前初始化

4. 验证字段一致性与权限

  • 确保Firestore文档中的字段名与Usuario类的属性名完全一致(大小写敏感),所有非可选字段(如nombre、telefono等)在文档中必须存在且非空;
  • 检查Firestore安全规则,确认当前用户有权限读取Usuarios集合下的文档,若规则限制未认证用户读取,需确保用户已登录。

内容的提问来源于stack exchange,提问作者Monrac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:01:19