如何根据TableView选中的单元格修改字典数组中的对应元素值
最优方案是通过闭包建立反向数据回传链路,同时修改数据模型的可变性,具体实现步骤如下:
问题根源
- 你的
TradeList中的trades数组用let声明,本身就不允许修改 Trade和TradeList都是结构体(值类型),页面间传递的是数据副本,修改副本不会影响主页面的原数组- 没有建立数据回传链路,编辑后的新数据无法传递回主页面更新原数组
步骤1:修改数据模型,支持数据修改
首先确保Trade结构体的属性为可修改的var,同时把TradeList中的trades改为var:
// Trade 结构体示例(如果原来属性是let要改成var) struct Trade { var ticker: String var name: String } // 修改TradeList struct TradeList { // 把let改为var,支持修改数组内容 var trades: [Trade] = [ Trade(ticker: "AAPL", name: "Apple"), Trade(ticker: "AMD", name: "Advanced Micro Devices") ] }
步骤2:给EditViewController添加保存回调
在EditViewController中新增闭包属性,点击保存时将新数据通过闭包传出:
class EditViewController: UIViewController { var editTitle: String? var editPrice: String? // 新增保存回调,参数为修改后的代码和名称 var saveCompletion: ((_ newTicker: String, _ newName: String) -> Void)? @IBOutlet weak var editTitleField: UITextField! @IBOutlet weak var editPriceField: UITextField! override func viewDidLoad() { super.viewDidLoad() editTitleField.text = editTitle editPriceField.text = editPrice } @IBAction func editSaveButton(_ sender: UIButton) { guard let newTicker = editTitleField.text, !newTicker.isEmpty, let newName = editPriceField.text, !newName.isEmpty else { // 可自行添加输入为空的提示逻辑 return } // 传出新数据 saveCompletion?(newTicker, newName) dismiss(animated: true) } }
步骤3:给DetailViewController新增属性和回调
在DetailViewController中新增存储选中下标的属性,以及编辑完成的回调,同时在跳转EditViewController时接收保存回调:
class DetailViewController: UIViewController { let trade: Trade // 新增:存储当前数据在数组中的下标 var selectedIndex: Int! // 新增:编辑完成回调,参数为下标、新代码、新名称 var editCompletion: ((_ index: Int, _ newTicker: String, _ newName: String) -> Void)? @IBOutlet var tickerLabel: UILabel! @IBOutlet var nameLabel: UILabel! // 原有初始化、viewDidLoad等代码不变... override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "DetailVCToEditVC" { let displayVC = segue.destination as! EditViewController displayVC.editTitle = tickerLabel.text displayVC.editPrice = nameLabel.text // 接收编辑页的保存回调 displayVC.saveCompletion = { [weak self] newTicker, newName in guard let self = self else { return } // 更新当前详情页显示 self.tickerLabel.text = newTicker self.nameLabel.text = newName // 把新数据和下标传给主页面 self.editCompletion?(self.selectedIndex, newTicker, newName) } } } }
步骤4:主ViewController接收回调,更新数组和表格
修改主ViewController的segue方法,给DetailViewController的回调赋值,收到新数据后更新原数组,刷新对应表格行:
@IBSegueAction func showDetailView(_ coder: NSCoder) -> DetailViewController? { guard let indexPath = tradeTableView.indexPathForSelectedRow else { fatalError("Nothing selected!")} let trade = tradesList.trades[indexPath.row] let detailVC = DetailViewController(coder: coder, trade: trade) // 传入选中行的下标 detailVC?.selectedIndex = indexPath.row // 接收编辑完成的回调 detailVC?.editCompletion = { [weak self] index, newTicker, newName in guard let self = self else { return } // 更新原数组对应位置的数据 self.tradesList.trades[index].ticker = newTicker self.tradesList.trades[index].name = newName // 只刷新对应行,性能更好 self.tradeTableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic) } return detailVC }
这种方案是iOS页面间反向传值的标准最优实现,逻辑清晰耦合度低,不需要用到通知、单例等高耦合的方案。
内容的提问来源于stack exchange,提问作者kriskrossy
相关产品推荐
相关产品推荐

