Swift 3:从ViewController2修改ViewController1按钮标题不生效问题求助
Hey there, let's break down what's going wrong here and get your button title updating properly!
The Root of the Problem
Take a look at this line in your ViewController2's dismissHandler:
dismiss(animated: true, completion:{ ViewController1().setButtonText() })
When you call ViewController1(), you're creating a brand new, completely separate instance of ViewController1—not referencing the one that's already displayed on your screen. This new instance never gets presented, so when you call setButtonText() on it, you're modifying a button that no one can see. That's why you only see changes when you re-show the original ViewController1 or trigger its internal buttons: you're finally interacting with the correct instance.
Fix 1: Use a Closure (Simple & Direct)
Closures are a clean way to pass a callback from ViewController2 back to the original ViewController1. Here's how to implement it:
Update ViewController2
Add a closure property to hold the callback, then call it when dismissing:
class ViewController2: UIViewController { // Add a closure to trigger the title update var onTitleSaved: (() -> Void)? override func viewDidLoad() { super.viewDidLoad() newTitleTextField.placeholder = "Set New Title" dismissButton.setTitle("Save and Dismiss", for: .normal) dismissButton.addTarget(self, action: #selector(dismissHandler), for: .touchUpInside) } @objc func dismissHandler(){ // First update your Title.buttonA with the text field input Title.buttonA = newTitleTextField.text ?? "" dismiss(animated: true) { // Call the closure to notify ViewController1 to update the button self.onTitleSaved?() } } }
Update ViewController1
Pass the setButtonText method to the closure when presenting ViewController2:
class ViewController1: UIViewController { @IBOutlet weak var buttonA: UIButton! override func viewDidLoad() { super.viewDidLoad() buttonA.setTitle("FirstEdit", for: .normal) newViewController.addTarget(self, action: #selector(newVCHandler), for: .touchUpInside) } @objc func newVCHandler(){ let vc2 = ViewController2() // Assign the closure to trigger our setButtonText method vc2.onTitleSaved = { [weak self] in self?.setButtonText() } present(vc2, animated: true, completion: nil) } func setButtonText(){ buttonA.setTitle("\(Title.buttonA)", for: .normal) } }
The [weak self] prevents a memory leak (since ViewController1 holds ViewController2, and the closure would otherwise hold ViewController1 in a cycle).
Fix 2: Use Delegation (Great for Complex Interactions)
If you need to pass more data or have multiple callbacks later, delegation is a standard iOS pattern:
Step 1: Define a Delegate Protocol
protocol ViewController2Delegate: AnyObject { func didFinishUpdatingTitle() }
Step 2: Add Delegate Property to ViewController2
class ViewController2: UIViewController { weak var delegate: ViewController2Delegate? override func viewDidLoad() { super.viewDidLoad() // ... existing viewDidLoad code } @objc func dismissHandler(){ Title.buttonA = newTitleTextField.text ?? "" dismiss(animated: true) { self.delegate?.didFinishUpdatingTitle() } } }
Step 3: Conform ViewController1 to the Delegate
class ViewController1: UIViewController, ViewController2Delegate { // ... existing code @objc func newVCHandler(){ let vc2 = ViewController2() vc2.delegate = self present(vc2, animated: true, completion: nil) } // Implement the delegate method func didFinishUpdatingTitle() { setButtonText() } // ... existing setButtonText code }
Why These Fixes Work
Both approaches ensure you're calling setButtonText() on the actual instance of ViewController1 that's displayed on screen, not a throwaway new instance. This way, the button title updates immediately when you dismiss ViewController2.
内容的提问来源于stack exchange,提问作者Skiddswarmik

