You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用Protocol与Delegate实现StateListVC到PlayVC的页面跳转?

Fixing Delegate Navigation from PlaceVC to PlayVC via StateListVC

Hey there! I see the issue with your delegate setup—let's break down what's going wrong and fix it step by step.

The Core Problem

In your StateListVC's viewWillAppear method, you're creating a new instance of PlaceVC and setting its delegate, but this isn't the same PlaceVC that's inside your container view. The container view loads its child view controllers automatically from the storyboard, so your manual instance is never displayed, leaving the actual displayed PlaceVC's delegate as nil.

Step 1: Properly Assign the Delegate to the Container's PlaceVC

Instead of creating a new PlaceVC, we need to get the existing instance that's already in the container view. You can do this either by using prepare(for:sender:) (if you have a segue connected to the container) or by iterating through childViewControllers in viewDidLoad.

Option 1: Using prepare(for:sender:) (Recommended)

First, set a segue identifier for your container view's segue in the storyboard (e.g., "ContainerToPlaceVC"). Then update StateListVC:

class StateListVC: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    // This method catches segues to child view controllers (like your container's PlaceVC)
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "ContainerToPlaceVC" {
            if let placeVC = segue.destination as? PlaceVC {
                placeVC.delegate = self
            }
        }
    }
}

extension StateListVC: MoveToAnotherVC {
    func moving(string: String) {
        print(string)
        // Now navigate to PlayVC here
        if let playVC = storyboard?.instantiateViewController(withIdentifier: "PlayVC") as? PlayVC {
            // Use navigation controller push if StateListVC is in a nav stack
            navigationController?.pushViewController(playVC, animated: true)
            // Or present modally if needed:
            // present(playVC, animated: true)
        }
    }
}

Option 2: Iterate Through Child View Controllers

If you don't want to use segues, you can find PlaceVC in viewDidLoad:

class StateListVC: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Find the PlaceVC among child view controllers
        let placeVC = childViewControllers.first(where: { $0 is PlaceVC }) as? PlaceVC
        placeVC?.delegate = self
    }
}

// Keep the MoveToAnotherVC extension the same as above

Step 2: Fix PlaceVC's TableView Selection Logic

Remove the undefined isMoveToAnotherVC variable and ensure the delegate call works correctly:

protocol MoveToAnotherVC: AnyObject { // Add AnyObject to make it a class-only protocol (safer for delegates)
    func moving(string: String)
}

class PlaceVC: UIViewController {
    @IBOutlet weak var tableViewPlace: UITableView!
    weak var delegate: MoveToAnotherVC? // Use weak to avoid retain cycles
    var arrPlace = ["Place1", "Place2"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableViewPlace.dataSource = self
        tableViewPlace.delegate = self
    }
}

extension PlaceVC: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return arrPlace.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = arrPlace[indexPath.row]
        return cell
    }
}

extension PlaceVC: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard let delegate = delegate else {
            print("Delegate not set")
            return
        }
        delegate.moving(string: arrPlace[indexPath.row]) // Pass the selected place if needed
        // Deselect the row for better UX
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

Key Improvements Added

  • Weak Delegate: Marked delegate as weak and made the protocol AnyObject to prevent retain cycles (critical for memory management).
  • Correct Delegate Assignment: Targeted the actual PlaceVC instance in the container view, not a new one.
  • Navigation Logic: Added code to push/present PlayVC in the delegate method.
  • UX Polish: Added tableView.deselectRow for better user experience.

Now when you tap a row in PlaceVC, the delegate will trigger moving(string:) in StateListVC, which will navigate to PlayVC as expected!

内容的提问来源于stack exchange,提问作者AR Tunes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:05:34