Swift调用ObservableObject时崩溃,Firebase文件上传无报错
问题:Swift ObservableObject调用时崩溃无报错,Firebase集合/文档创建失败
我正在开发一个Swift的ObservableObject类,每次调用这个对象时程序就崩溃,而且没有任何报错信息。查了Firebase API文档也没找到明确原因。我的需求是调用该对象时,能在Firebase中创建新的集合和文档,相关代码如下:
import Foundation import FirebaseFirestore import FirebaseStorage import FirebaseFirestoreSwift enum Action { case Upload case Download } enum TransferType { case URL(Address: String) case Firebase(Collection: String, DocumentID: String) } enum ModelType { //MARK: - #1 //Different Types of Model Types that will be uploaded and downloaded case ActiveJobsite case UserData } class JsonRequest: ObservableObject { let db = Firestore.firestore() @Published var URL: String? //MARK: - #2 //Temporary optionals for each custom model type @Published var ActiveJobsite: [ActiveJob]? @Published var UserData: UsersData? //Status of Upload-Download Request @Published var Completed: Bool = false @Published var Fetching: Bool = false @Published var CollectionID: String? @Published var DocumentID: String? func JsonRequest(TransferType: TransferType, ModelType: ModelType, Action: Action) { if Action == .Download { DownloadJson() } else if Action == .Upload { UploadJson(ModelType: ModelType, TransferType: TransferType) } else { //Errpr } } func DownloadJson(){ // db.addDocument(data: <#T##[String : Any]#>) } func UploadJson(ModelType: ModelType, TransferType: TransferType) { let JsonEncoder = JSONEncoder() JsonEncoder.outputFormatting = .prettyPrinted // case Firebase switch TransferType { case .Firebase(let Collection, let DocumentID): //Test If Document Exsists //MARK: - #3 //Make a encoder for Each Model Type //ActiveJob Encoder if ModelType == .ActiveJobsite { if let Jobsite = self.ActiveJobsite { do { let encodedData = try JsonEncoder.encode(Jobsite) FirebaseUpload(Collection: Collection, DocumentId: DocumentID, Data: encodedData) } catch { //error } } } //UserData Encoder if ModelType == .UserData { if let UserData = self.UserData { do { let encodedData = try JsonEncoder.encode(UserData) FirebaseUpload(Collection: Collection, DocumentId: DocumentID, Data: encodedData) } catch { //error } } } case .URL(let address): UploadError(Address: address) } } func FirebaseUpload(Collection: String, DocumentId: String, Data: Data) { //Test If Document Exsists let File = db.collection("\(Collection)").document("\(DocumentId)") do { if let json = try JSONSerialization.jsonObject(with: Data, options: []) as? [String : Any] { File.setData(json) } else { //Error print("errorMsg") } } catch { print("errorMsg") } } func UploadError(Address: String) { print("Cant Upload to URL: \(Address)") } }
崩溃原因排查与修复方案
1. 类名与方法名冲突
你的类名为JsonRequest,但内部定义了同名方法func JsonRequest(...),这会和类的构造逻辑冲突。Swift中与类同名的方法会被识别为构造器,但该方法未遵循构造器规则,调用时直接引发崩溃。
修复:
将方法改名并调整参数命名规范:
func performRequest(transferType: TransferType, modelType: ModelType, action: Action) { fetching = true completed = false switch action { case .Upload: uploadJson(modelType: modelType, transferType: transferType) case .Download: downloadJson() } }
2. JSON格式不兼容Firestore文档结构
ActiveJobsite是数组类型[ActiveJob],编码后为JSON数组,但Firestore文档要求必须是键值对(字典)结构。直接将数组转[String: Any]会失败,后续逻辑异常引发崩溃。
修复:
上传数组时将其包装进字典,适配Firestore要求:
// 在UploadJson的ActiveJobsite分支中 if let Jobsite = self.ActiveJobsite { do { // 把数组包装为字典 let wrappedData = ["jobsites": Jobsite] let encodedData = try JsonEncoder.encode(wrappedData) FirebaseUpload(Collection: Collection, DocumentId: DocumentID, Data: encodedData) } catch { print("编码失败:\(error.localizedDescription)") } }
3. 错误处理缺失具体信息
代码中仅用print("errorMsg")处理错误,无法获取具体崩溃原因(比如模型未遵循Codable、Firebase初始化失败等),导致排查无据。
修复:
打印具体错误信息,同时确保模型类遵循Codable协议:
// 编码错误处理 catch { print("ActiveJob编码失败:\(error.localizedDescription)") } // 模型类示例 struct ActiveJob: Codable { // 模型属性 } struct UsersData: Codable { // 模型属性 }
4. Firebase异步操作未处理回调
setData是异步方法,当前代码未处理完成回调,Completed状态更新不及时,可能导致依赖状态的逻辑异常。
修复:
添加闭包回调更新状态:
func FirebaseUpload(Collection: String, DocumentId: String, Data: Data, completion: @escaping (Error?) -> Void) { let File = db.collection(Collection).document(DocumentId) do { if let json = try JSONSerialization.jsonObject(with: Data) as? [String : Any] { File.setData(json) { error in completion(error) } } else { completion(NSError(domain: "JsonRequest", code: -1, userInfo: [NSLocalizedDescriptionKey: "JSON格式不兼容"])) } } catch { completion(error) } }
调用时更新状态:
FirebaseUpload(Collection: Collection, DocumentId: DocumentID, Data: encodedData) { [weak self] error in DispatchQueue.main.async { self?.Fetching = false self?.Completed = error == nil if let error = error { print("上传失败:\(error)") } } }
5. 命名规范混乱
代码中大小写不统一(如DownloadJson、ActiveJobsite),增加调试难度,建议遵循Swift规范:
- 类/枚举名:大驼峰(如
JsonRequest) - 方法/变量名:小驼峰(如
downloadJson、activeJobsite)
内容的提问来源于stack exchange,提问作者Thea Young
相关产品推荐
相关产品推荐

