在Init中调用函数设变量,拆分ContactInfo数组遇未初始化错误
解决ContactInfo拆分数组初始化&Init调用函数的问题
嗨,我正好做过类似的个人资料模块,给你捋捋怎么搞定这两个问题:
1. 先解决数组未初始化报错的问题
Swift是强类型语言,非可选的存储属性必须在实例初始化完成前拥有确定的值,所以最省心的方式是提前给三个数组设初始值——直接初始化为空数组就行,既能避免报错,还不用后续处理可选类型的解包麻烦。
假设你的基础数据模型是这样的(可以根据实际情况调整):
// 用户基础信息模型 struct Contact { let userID: String // 其他如昵称、头像等信息... } // 联系方式汇总模型 struct ContactInfo { let phoneNumbers: [String]? // 可能是可选数组,也可能是必选 let emails: [String]? let addresses: [Address]? // 地址用自定义模型存储 } // 地址详情模型 struct Address { let street: String let city: String let zipCode: String }
那三个拆分后的数组就这么定义:
// 在ViewModel或者ViewController中声明 var contactInfoPhoneList: [String] = [] var contactInfoEmailList: [String] = [] var contactInfoAddressList: [Address] = []
空数组是合法的初始值,后续再填充数据就不会有问题了。
2. 在Init里调用函数拆分数据
不管你是用ViewModel分离业务逻辑,还是直接在ViewController里处理,都可以在初始化方法里传入contact和contactInfo,然后立即调用拆分函数填充数组。
推荐用ViewModel的实现方式(更清晰的架构)
class ContactProfileViewModel { let contact: Contact var contactInfoPhoneList: [String] = [] var contactInfoEmailList: [String] = [] var contactInfoAddressList: [Address] = [] // 初始化时直接传入两个变量,并调用解析函数 init(contact: Contact, contactInfo: ContactInfo) { self.contact = contact self.parseContactInfo(contactInfo) } // 私有函数:把ContactInfo的内容拆分到三个数组中 private func parseContactInfo(_ info: ContactInfo) { // 如果ContactInfo里的属性是可选类型,用空数组兜底避免nil contactInfoPhoneList = info.phoneNumbers ?? [] contactInfoEmailList = info.emails ?? [] contactInfoAddressList = info.addresses ?? [] // 要是属性是必选非可选的,直接赋值即可: // contactInfoPhoneList = info.phoneNumbers } }
直接在ViewController里处理的方式
class ContactProfileVC: UITableViewController { let contact: Contact let contactInfo: ContactInfo var contactInfoPhoneList: [String] = [] var contactInfoEmailList: [String] = [] var contactInfoAddressList: [Address] = [] // 自定义初始化方法 init(contact: Contact, contactInfo: ContactInfo) { self.contact = contact self.contactInfo = contactInfo super.init(style: .insetGrouped) // 选择你需要的TableView风格 // 调用数据拆分函数 setupContactData() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupContactData() { contactInfoPhoneList = contactInfo.phoneNumbers ?? [] contactInfoEmailList = contactInfo.emails ?? [] contactInfoAddressList = contactInfo.addresses ?? [] // 数据准备完成后刷新TableView tableView.reloadData() } // 实现TableView数据源方法,对应三个分区展示内容 override func numberOfSections(in tableView: UITableView) -> Int { return 3 // 电话、邮箱、地址三个分区 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { case 0: return contactInfoPhoneList.count case 1: return contactInfoEmailList.count case 2: return contactInfoAddressList.count default: return 0 } } // 配置Cell内容 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath) switch indexPath.section { case 0: cell.textLabel?.text = contactInfoPhoneList[indexPath.row] case 1: cell.textLabel?.text = contactInfoEmailList[indexPath.row] case 2: let address = contactInfoAddressList[indexPath.row] cell.textLabel?.text = "\(address.street), \(address.city) \(address.zipCode)" default: break } return cell } }
额外注意点
- 如果
ContactInfo里的属性是必选非可选类型,直接赋值即可,不用?? []兜底; - 若地址是更复杂的结构,确保你的
Address模型初始化逻辑正确; - 用ViewModel的话,后续TableView的数据源可以直接绑定ViewModel里的数组,代码耦合度更低、更易维护。
内容的提问来源于stack exchange,提问作者user3628240
相关产品推荐
相关产品推荐

