Swift 5中如何从第二个视图控制器修改第一个的UIImage?
iOS 返回视图控制器后触发图片更新问题解决方法
问题描述
正在进行期末作业项目,需求为:从第一个视图控制器通过普通show segue进入第二个视图控制器的列表页面,点击列表条目后返回第一个控制器并修改其中的UIImage。
当前第二个控制器的点击返回代码:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { dismiss (animated: true, completion: nil) building = true print("\(squareType)") print("BUILDING = \(building)") }
希望返回后触发第一个控制器的farmCreator方法更新图片,该方法代码:
func farmCreator() { for i in 0...24 { if allCells[i].material == "Forest" && squareType == "Cabin" { imageBottom[i].image = UIImage(named:"Farms/2") } if allCells[i].material == "Forest" && squareType == "Forest Mine" { imageBottom[i].image = UIImage(named:"Farms/1") //Change } if allCells[i].material == "Rock" && squareType == "Mine" { imageBottom[i].image = UIImage(named:"Farms/1") } if allCells[i].material == "Water" && squareType == "Fishmonger" { imageBottom[i].image = UIImage(named:"Farms/3") } if allCells[i].material == "Water" && squareType == "Water Mine" { imageBottom[i].image = UIImage(named:"Farms/1") //Change } if allCells[i].material == "Plains" && squareType == "Farm"{ imageBottom[i].image = UIImage(named:"Farms/4") } if allCells[i].material == "Plains" && squareType == "Plain Mine"{ imageBottom[i].image = UIImage(named:"Farms/1") //Change } } }
已在两个控制器间传递相关参数,但图片无法更新。尝试重写第一个控制器的视图生命周期方法(viewDidDisappear、viewWillDisappear等),发现这些方法仅在被dismiss的第二个控制器上触发,第一个控制器的对应方法无响应。询问是否需要使用unwind segue及实现方式。
解决方案
方法一:使用Unwind Segue实现返回后触发更新
步骤1:在第一个视图控制器中定义unwind方法
在第一个控制器(假设类名为FirstViewController)中添加带@IBAction标记的unwind方法,方法必须接收UIStoryboardSegue参数:
@IBAction func unwindToFirstVC(_ segue: UIStoryboardSegue) { // 获取第二个控制器传递的参数 if let secondVC = segue.source as? SecondViewController { self.squareType = secondVC.squareType self.building = secondVC.building // 调用farmCreator更新图片 farmCreator() } }
步骤2:在Storyboard中创建Unwind Segue
- 打开Storyboard,选中第二个视图控制器的TableViewCell(或整个控制器)。
- 按住
Ctrl键,拖动到第二个控制器顶部的Exit图标(绿色退出箭头)上。 - 在弹出菜单中选择刚定义的
unwindToFirstVC:方法。 - 选中这个unwind segue,在右侧属性面板中设置标识符(例如
unwindToFirst)。
步骤3:修改第二个控制器的点击事件代码
替换原dismiss代码,改为触发unwind segue:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 先设置需要传递的参数(根据你的数据源逻辑设置squareType) building = true squareType = yourDataSourceArray[indexPath.row] // 替换为你的数据源获取逻辑 print("\(squareType)") print("BUILDING = \(building)") // 触发unwind segue返回并传递参数 performSegue(withIdentifier: "unwindToFirst", sender: self) }
方法二:用闭包回调实现(无需Storyboard操作)
如果不想依赖Storyboard,可使用闭包回调:
- 在第二个控制器中定义闭包属性:
var updateImageHandler: ((String, Bool) -> Void)? // 带参数的闭包,传递squareType和building
- 在第一个控制器跳转到第二个控制器时,设置闭包:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let secondVC = segue.destination as? SecondViewController { secondVC.updateImageHandler = { [weak self] squareType, building in guard let self = self else { return } self.squareType = squareType self.building = building self.farmCreator() } } }
- 修改第二个控制器的点击事件:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { building = true squareType = yourDataSourceArray[indexPath.row] print("\(squareType)") print("BUILDING = \(building)") // 调用闭包通知第一个控制器更新 updateImageHandler?(squareType, building) // 关闭当前控制器返回 dismiss(animated: true, completion: nil) }
内容的提问来源于stack exchange,提问作者Superpig0
相关产品推荐
相关产品推荐

