【问题标题】:Cannot update embedded child VC from non-parent VC无法从非父 VC 更新嵌入的子 VC
【发布时间】:2017-01-21 00:44:36
【问题描述】:

最新的 Xcode/Swift/iOS。

我有一个主 VC(称为 StartVC),它包含一个通过和嵌入式 segue 的子 VC(称为 TopBarVC)。 Child VC 包含一个按钮,当按下该按钮时,会模态地连接到第三个 VC(称为 CategoryPickerOverlayVC)(此 VC 中的视图用作选择类别的下拉框)。

    @IBAction func CategoryFilterButtonPressed(_ sender: Any) {

    performSegue(withIdentifier: "toCategoryPickerOverlay", sender: self)

}

当从下拉框中选择一个选项时,该选项本身由三个按钮组成,应使用所选按钮的标题替换子VC中按钮的标题文本。

在主 VC 中,我使用 prepareforsegue 将子 VC 的引用存储在一个变量中 - “topBarReference” - 在嵌入 segue 发生的那一刻。

 var topBarReference: TopBarVC?


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {        
    if segue.identifier == "TopBarPane"{
        topBarReference = segue.destination as? TopBarVC
    }
}

然后,在第三个 VC 中,当我单击下拉框中的按钮选项之一时,按钮标题通过 prepareforsegue 发送以更新子 VC 中的按钮(通过“topBarReference”)。

        if segue.identifier == "unwindToStartVC"{

        let vc = segue.destination as! StartVC

        vc.topBarReference?.filterButtonText = ((sender as! UIButton).titleLabel?.text)!

    }

然后,第三个 VC 放松回到主 VC。我应该补充一点,当 Child VC 中的按钮发生更改时,Child VC 中的变量(filterButtonText)首先设置标题文本,然后使用该变量通过 Child VC 的 viewDidAppear 方法设置按钮标题文本。

使用调试器时,我还注意到主 VC 中的 viewDidAppear 在展开后似乎没有执行(我在 viewDidAppear 中放置了诊断打印到控制台,展开后没有任何打印)。我意识到这可以解释按钮没有更新,但我不知道为什么 viewDidAppear 没有运行。

我也尝试过使用委托协议和 instantiateViewController(withString:) 无济于事。所有方法都产生相同的结果,即 Child VC 中的按钮没有得到更新。没有显示错误。其他一切都按预期进行。

关于我做错了什么有什么想法吗?

【问题讨论】:

  • 如果两者都“嵌入”到 StartVC 中,即 StartVC 仍在被看到,则不会调用确实出现的视图。尝试使用通知。让您的 startVC 监听特定通知,并在您放松/从下拉列表中选择一个选项时将其发送出去。在通知处理程序代码中,更新按钮标题
  • 第三个 VC 是一个单独的 VC,不是嵌入的。
  • “我不知道为什么 viewDidAppear 不运行”因为它从未消失。我想这也是@ShawnFrank 告诉你的。
  • @Rossco,试试Shawn Frank的评论,可以在Master VC的viewDidDisappear方法中测试,如果执行segue时执行。
  • @Shawn Frank:感谢您的回复 - 我还没有使用通知(尽管我知道它们),所以会在某个时候进行查找。我很有信心,我的原始代码应该可以工作,所以我想找人指出原因,而不是直接改变更新按钮文本的机制。

标签: ios swift xcode uicontainerview viewdidappear


【解决方案1】:

你的意思是这样的吗?

如果是这样,我使用的解决方案很简单:第三个VC使用prepareForSegue设置嵌入式VC的属性,嵌入式VC在unwind方法中获取该属性。

在我的实现中,三个视图控制器分别称为 ViewController、ChildViewController 和 ThirdViewController。这是整个代码(其他一切都在情节提要中配置):

class ChildViewController: UIViewController {

    @IBOutlet weak var theButton: UIButton!
    var buttonTitle : String?

    @IBAction func unwind(_:UIStoryboardSegue) {
        self.theButton.setTitle(self.buttonTitle, for: .normal)
    }

}
class ThirdViewController: UIViewController {

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        (segue.destination as! ChildViewController).buttonTitle = (sender as! UIButton).currentTitle
    }

}

【讨论】:

    【解决方案2】:

    好的,所以我发现我的原始代码在 Child VC 的 prepareforsegue 中的一行代码工作正常。如果我从以下位置更改 prepareforsegue:

            if segue.identifier == "unwindToStartVC"{
    
            let vc = segue.destination as! StartVC
            vc.topBarReference?.CategoryFilterButton.titleLabel?.text = ((sender as! UIButton).titleLabel?.text)!
    
        }
    

    到这里:

            if segue.identifier == "unwindToStartVC"{
    
            let vc = segue.destination as! StartVC
            vc.topBarReference?.CategoryFilterButton.setTitle((sender as! UIButton).titleLabel?.text, for: .normal)
    
        }
    

    它工作得很好。 .setTitle 方法的使用似乎有所不同,尽管我不知道为什么。

    感谢 Matt 给了我改变它的想法。当我尝试时,Matt 的方法确实有效,但是,由于我正在放松到 Master VC 而不是 Child VC,因此我必须根据我放置它的位置相应地编辑代码。

    由于我的小“发现”相当于对原始代码的最小更改,因此我将其标记为答案。

    感谢大家抽出宝贵时间回复!

    【讨论】:

      猜你喜欢
      • 2021-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      • 2011-07-30
      相关资源
      最近更新 更多