继承ObservableObject的DetailViewModel类报无初始化器错误原因求解
错误产生原因
- Swift的类初始化安全规则要求:所有非可选类型的存储属性,必须在类实例初始化完成前被赋予确定的值,不允许处于未定义状态
- 你代码中的
strInstructions、strIngredient、strMeasure三个String类型属性,均为非可选类型:既没有像strMeal一样直接设置默认空字符串,也没有自定义init初始化方法为这三个属性赋值,不符合Swift的初始化规则,因此触发该报错。 - 额外说明:你的
strMealThumb是URL?可选类型,系统会自动为可选类型属性分配默认值nil,所以不需要额外初始化也不会报错。
解决方法
有两种常用方案可修复该问题:
方案1:为所有非可选属性设置默认值
如果你的属性值需要后续通过网络请求等异步操作赋值,推荐用该方案,先给属性赋值默认空值即可:
import Foundation import UIKit @MainActor class DetailViewModel: ObservableObject{ @Published var strMeal: String = "" @Published var strInstructions: String = "" // 新增默认空值 @Published var strIngredient: String = "" // 新增默认空值 @Published var strMeasure: String = "" // 新增默认空值 @Published var strMealThumb:URL? private func loadMealDetails(idMeal: String) async { do { let mealDetailResponse = try await WebServiceRequest().loadData(url: Constants.Urls.getMealByIdUrl(strMeal)) { data in return try? JSONDecoder().decode(MealDetailModel.self, from:data ) } } catch { print(error) } } }
方案2:自定义初始化方法
如果你需要在创建ViewModel实例时就为属性赋值,可以自定义init初始化器完成赋值:
import Foundation import UIKit @MainActor class DetailViewModel: ObservableObject{ @Published var strMeal: String = "" @Published var strInstructions: String @Published var strIngredient: String @Published var strMeasure: String @Published var strMealThumb:URL? // 自定义初始化方法 init(strInstructions: String, strIngredient: String, strMeasure: String, strMealThumb: URL? = nil) { self.strInstructions = strInstructions self.strIngredient = strIngredient self.strMeasure = strMeasure self.strMealThumb = strMealThumb } private func loadMealDetails(idMeal: String) async { do { let mealDetailResponse = try await WebServiceRequest().loadData(url: Constants.Urls.getMealByIdUrl(strMeal)) { data in return try? JSONDecoder().decode(MealDetailModel.self, from:data ) } } catch { print(error) } } }
内容的提问来源于stack exchange,提问作者Wen Love Howard
相关产品推荐
相关产品推荐

