iOS开发:Segue关闭时不使用viewWillAppear,如何调用原VC方法?
Great question—using viewWillAppear here isn’t ideal because it runs every time your original VC comes back into view, even if the user didn’t submit anything (like tapping the back button without sending). Instead, we can use delegation or completion closures to specifically trigger your method only when the submission is complete and the Reply VC is dismissed.
Approach 1: Delegation (Traditional & Type-Safe)
This is the standard iOS pattern for passing events back up the view controller hierarchy.
Step 1: Define a Delegate Protocol in the Reply VC
Add this to your Reply.swift file:
// Define a protocol to communicate submission events protocol ReplyDelegate: AnyObject { // Customize this method if you need to pass data back (e.g., the submitted text) func replyDidSuccessfullySubmit() } class Reply: UIViewController { // Your existing properties: var blogName: String! @IBOutlet weak var replyTextView: UITextView! // Add a weak delegate property to avoid retain cycles weak var delegate: ReplyDelegate? // Send button action @IBAction func sendButtonTapped(_ sender: UIBarButtonItem) { // 1. Submit your text to the server here let submittedContent = replyTextView.text ?? "" // ... perform API call ... // 2. After successful submission, notify the delegate and dismiss delegate?.replyDidSuccessfullySubmit() // If you need to pass data back: // delegate?.replyDidSuccessfullySubmit(content: submittedContent) dismiss(animated: true) } }
Step 2: Conform to the Delegate in Your Original VC
Update your original ViewController to adopt the ReplyDelegate protocol and implement the required method:
class YourOriginalViewController: UIViewController, ReplyDelegate { // Your existing code... override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == blogSegueIdentifier { let destination = segue.destination as! Reply let path = tableView.indexPathForSelectedRow let cell = tableView.cellForRow(at: path!) as! QuestionsTabCell destination.blogName = String(cell.labelQues!.tag) // Set the delegate to self so we receive the submission event destination.delegate = self } } // Implement the delegate method to trigger your desired action func replyDidSuccessfullySubmit() { // Call your method here—e.g., refresh the table view or update data self.refreshQuestions() // Replace with your actual method name } // If you passed data back: // func replyDidSuccessfullySubmit(content: String) { // // Handle the submitted content // } }
Approach 2: Completion Closures (Concise & Flexible)
If you prefer a more lightweight approach without defining a protocol, use a completion closure.
Step 1: Add a Completion Property to the Reply VC
Modify Reply.swift:
class Reply: UIViewController { var blogName: String! @IBOutlet weak var replyTextView: UITextView! // Add a completion closure (optional, since the user might cancel) var onSubmissionComplete: (() -> Void)? // Or pass data back: var onSubmissionComplete: ((String) -> Void)? @IBAction func sendButtonTapped(_ sender: UIBarButtonItem) { // 1. Submit to server let submittedContent = replyTextView.text ?? "" // ... API call ... // 2. Execute the closure before dismissing onSubmissionComplete?() // If passing data: onSubmissionComplete?(submittedContent) dismiss(animated: true) } }
Step 2: Assign the Closure in prepare(for:sender:)
Update your original VC's prepare method:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == blogSegueIdentifier { let destination = segue.destination as! Reply let path = tableView.indexPathForSelectedRow let cell = tableView.cellForRow(at: path!) as! QuestionsTabCell destination.blogName = String(cell.labelQues!.tag) // Assign the closure to trigger your method destination.onSubmissionComplete = { [weak self] in guard let self = self else { return } // Avoid retain cycles with weak self self.refreshQuestions() // Your method here } // If passing data: // destination.onSubmissionComplete = { [weak self] content in // self?.handleSubmittedContent(content) // } } }
Why These Work Better Than viewWillAppear
- Intentional Triggering: These methods only run when the user actually submits content, not every time the original VC becomes visible.
- Data Passing: You can easily send the submitted text back to the original VC if needed.
- Avoids Unnecessary Work:
viewWillAppearmight run logic you don't want (like refreshing data) if the user navigates back without submitting.
内容的提问来源于stack exchange,提问作者Scripy




