当从另一个控制器(弹出窗口)访问 UILabel(作为一个插座)时,它仍然为零

Posted

技术标签:

【中文标题】当从另一个控制器(弹出窗口)访问 UILabel(作为一个插座)时,它仍然为零【英文标题】:UILabel (as an outlet) remains nil when accessing it from another controller (popup window) 【发布时间】:2018-12-24 09:10:09 【问题描述】:

有 2 个控制器。 this is how the UI looks this is how I am creating the popup i.e. using segue

主页视图控制器: 有一个标签和一个按钮。点击这个名为 --> 'add action' 的按钮 --> 会打开一个弹出窗口。

弹出视图控制器: 是一个弹出窗口,用户可以在其中输入输入并点击保存。在弹出窗口中,有一个文本字段。用户填写该字段并单击保存。 保存时 --> 为这个 PopupViewController 调用一个 IBAction,它具有解除弹出窗口的解除()函数。 并且关闭函数内的完成块是我试图实例化 HomeViewController 以更新标签的地方。 (注意:PopupViewController 是通过 segue 创建的,通过选择当前上下文)

但是在这样做的同时,我发现 HomeViewController 内的所有 IBOutlets 在尝试从弹出窗口中保存时都为零,因此我无法更新标签。

我尝试过的: 我已经检查了网络上的其他问答并在下面进行了验证: 1. 我检查了标签与故事板的连接。这是正确的。 2. 为了实例化,我使用了 instantiateViewController 语法 HomeViewController 正确。 但问题仍然存在。

HomeViewController

var actionNames = [String]()
var actionDescriptions = [String]()
@IBOutlet weak var firstActionLabel: UILabel!

func updateViewWithNewAction() 
    print("updating views started")
    if firstActionLabel != nil 
        if actionNames.count > 0 
            firstActionLabel.text = actionNames[0]
         else 
            print("no actions in the array")
        
     else 
        print("firstActionLabel is nil")
    
    print("updating views completed")


func addActions(actionName: String, actionDescription: String) 
    actionNames.append(actionName)
    actionDescriptions.append(actionDescription)
    print("actions added")

PopupViewController

@IBOutlet weak var actionTitle: UITextField!
@IBOutlet weak var actionDescriptionTextView: UITextView!
@IBAction func createAction(_ sender: Any) 
    //getting action values from user
    actionName = actionTitle.text!
    actionDescription = actionDescriptionTextView.text!

    dismiss(animated: true, completion: 
        print("completion block started ---")
        let homeVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController

        homeVC.addActions(actionName: self.actionName, actionDescription: self.actionDescription)
        homeVC.updateViewWithNewAction()
        print("completion block ended ---")
    )

预期结果:在 PopupViewController 的 createAction() 时,HomeViewController 内的标签应该更新为新值。 实际结果:在 homeVC.updateViewWithNewAction() 期间 firstActionLabel 为 nil

【问题讨论】:

您确定要在从 PopupViewController 关闭时实例化一个新的 HomeViewController 吗? 我愿意改变它。有没有其他方法可以更新 HomeViewController 中的标签?就我而言。 你能告诉我们代码,你在哪里显示弹出窗口吗? 你必须实现协议委托!!您无法实例化 HomeViewController,因为它已经实例化,并且在解雇您实例化新的 HomeViewController 时,这就是您看不到更新标签的原因。 @d4Rk 我添加了图像以显示我显示弹出窗口的位置。这不是通过代码,而是通过 segue。并选择“在当前上下文中” 【参考方案1】:

基本上我认为你想要这样的东西:

添加HomeViewController

override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if let popupViewController = segue.destination as? PopupViewController 
        popupViewController.callback = self.addActions
    

并在PopupViewController 中添加

var callback: ((String, String) -> Void)?

然后在PopupViewController

@IBAction func createAction(_ sender: Any) 
    //getting action values from user
    actionName = actionTitle.text!
    actionDescription = actionDescriptionTextView.text!

    dismiss(animated: true, completion: 
        callback?(self.actionName, self.actionDescription)
    )

【讨论】:

谢谢!这对我帮助很大。 :) 现在可以了。我想赞成你的回答,但我身边的代表太少了。我像这样更新了 PopupViewController:var addActions: ((String, String) -> Void)? var updateView: (() -> Void )? dismiss(animated: true, completion: print("completion block started ---") self.addActions?(self.actionName, self.actionDescription) self.updateView?() print("completion block ended ---") ) 和 HomeViewController 像这样使用您提到的正确准备语句。 很高兴听到,我可以帮助你!我认为您无论如何都可以接受答案:-) 哦,是的。刚刚做到了。【参考方案2】:

这样做

class HomeViewController: UIViewcontroller 

    func viewDidLoad() 
        super.viewDidLoad()
        updateViewWithNewAction() 
    

问题是,直到viewDidLoad,你们中的任何一个IBOutlet 都不会被初始化。他们应该通过情节提要初始化。在viewDidLoad 之前,您无法获得任何参考。

如果您不想每次都调用updateViewWithNewAction(),则添加Bool 标志来决定是否调用updateViewWithNewAction()。在需要时从PopUpViewController 或任何其他位置设置Bool 标志。

【讨论】:

我认为一个更大的问题是,他没有将动作(无论如何)委托给 HomeViewController,而是实例化了一个新的 HomeVC ;-) @Ratul,这不是问题所在。我已经在这样做了。在我的情况下这并不重要,因为无论如何我都是从 PopupViewController 调用 updateViewWithNewAction() 如果你在假设什么,那么只要问@nayem,阅读 OP 问题but while doing so, I see that, all the IBOutlets inside of HomeViewController are nil upon trying to save from popup, therefore I am not able to update the labels.中的段落@ @d4Rk 是的,这是另一个问题,引入委托以与呈现它的视图控制器进行通信。但这取决于,因为这个弹出窗口可能是从任何其他视图控制器打开的,他可能想在没有事先的情况下故意打开HomeViewController,这在问题中没有发布。 可能,但不太可能。我只是更喜欢进行根本原因分析,以真正解决问题而不是解决症状。

以上是关于当从另一个控制器(弹出窗口)访问 UILabel(作为一个插座)时,它仍然为零的主要内容,如果未能解决你的问题,请参考以下文章

无法从另一个视图控制器更改 UILabel.text,UILabel 得到 nil 值

当从不同的类调用更改时,UIView IBOutlet 不会更改

无法从另一个视图控制器更改 UILabel 的文本

从另一个弹出窗口打开一个弹出窗口

当从另一个 ViewController 类调用方法时,Xcode 找到一个 nil 变量,其中不应该是任何变量

Kivy:从另一个弹出窗口中关闭一个弹出窗口