You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS开发:Segue关闭时不使用viewWillAppear,如何调用原VC方法?

How to Trigger a Method in the Original ViewController When Segue Closes (Without viewWillAppear)

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: viewWillAppear might run logic you don't want (like refreshing data) if the user navigates back without submitting.

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

火山引擎 最新活动