【问题标题】:Access IBOutlet from other View Controllers从其他视图控制器访问 IBOutlet
【发布时间】:2017-02-08 19:16:19
【问题描述】:

在 Stack Overflow 上有很多这样的问题,但似乎没有一个可以简单地回答我的具体问题。我希望能够在一个视图控制器上创建一个标签,该标签可以根据另一个视图控制器上的标签值来更改它显示的内容。我正在使用 Xcode 8.2.1 和 Swift 3。

编辑

FirstViewController

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showSecondViewController" {

        if let viewController = segue.destination as? SecondViewController {

            if messageLabel != nil {

                SecondViewController.billString = self.messageLabel //error on this line

            }
        }
    }
}

第二视图控制器

@IBOutlet weak var billLabel: UILabel!

var billString = "test"

override func viewDidLoad() {
    super.viewDidLoad()

    billLabel.text = billString

}

【问题讨论】:

  • 你能更具体一点吗?我相信您可以使用 prepareForSegue 来做到这一点,但仍然……您应该对此多加说明。
  • @i6x86 -- 我是一个相当新的程序员,所以我不确定我可以提供多少更多信息......第二个视图控制器上有一个标签,我想更改的值基于第一个视图控制器上的标签值。
  • 您在该标签上显示什么类型的数据,是字符串还是整数?
  • @i6x86 两个标签都包含字符串。
  • 这是 instance 变量,您尝试在 class 级别访问它。难怪编译器根本没有得到你;也许viewController.billString = ... 或类似的东西在这里看起来在语法上是正确的,但是您优雅地忽略了定义类型,似乎您尝试将UILabel 实例分配给String...这里有很多歧义,很难告诉你你想在这里做什么。

标签: swift uiviewcontroller xcode8 iboutlet


【解决方案1】:

你可以实现prepareForSegue:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "yourSegueIDHere" {
            if let viewController = segue.destination as? DestinationViewController {
              if(theVarContainingTheStringYouWantToSend !=nil){
                DestinationViewController.newVarContainigString = self.theVarContainingTheStringYouWantToSend 
               }
            }
        }
    }

您在 DestinationViewController 中创建 newVarContainigString 并为 segue 指定您想要的名称并将其放在显示 yourSegueIDHere 的位置,当您执行 segue 时,目标 vc 中的 var 将具有您发送的值。

我正在打电话,所以我不能 100% 确定此代码是否有效,但如果您有问题,可以询问。

【讨论】:

    【解决方案2】:

    这是一个我能够在 Playground 上超级快速完成的实现。这个想法是您创建一个协议和子类 UILabel 并使用调用协议方法的 didSet 覆盖其text 属性。

    class Label:UILabel {
        var delegate:LabelDelegate?
    
        override var text: String? {
            didSet {
                if let text = text {
                    self.delegate?.valueChanged(string: text)
                }
            }
        }
    }
    
    protocol delegate:LabelDelegate {
        func valueChanged(string:String)
    }
    
    class ViewControllerA:UIViewController {
        IBOutlet weak var label:Label!
    }
    
    class ViewControllerB:UIViewController, LabelDelegate {
        IBOutlet weak var label:UILabel!
    
        func viewDidLoad() {
            let a = A() // This is where you whould get a reference to ViewControllerA. Maybe using storyboardID or some other way
            a.label.delegate = self
        }
    
        internal func valueChanged(string: String) {
            //Check what the string variable is and set your label accordingly
            self.label.text = "Hello World"
        }
    }
    

    b.label 现在包含文本“Hello World”

    您可以使用 storyboardID 或某种方式将其调整为 UIViewController 实现以跟踪 ViewController,并假设您知道 UIViewController 的 nil 状态,您可以正确设置委托。

    【讨论】:

    • 感谢您的帮助。我是一个相当新的程序员——我会把这段代码放在我的视图控制器中的什么地方。在 viewDidLoad 下?另外——我不想让标签具有相同的价值,但我确实希望第一个影响第二个。 @Prientus
    • @AEquinox01 好吧,我会将 UILabel 子类和协议放入一个新文件中。然后在情节提要中,我将在右侧的身份检查器选项卡中为我的自定义类添加标签。然后在 ViewControllerA 中创建标签插座,以便它识别它的“标签”类,然后我会将委托 self.mylabel.delegate 放在 viewDidLoad 中,是的。之后,当您在 ViewControllerB 中实现valueChanged 方法时,您不必将其设置为传入的文本。您可以将其设置为任何您想要的。
    • PS:我更新了代码,使其与 ViewController Scheme 更相关
    • 我能够以另一种方式解决它。谢谢你的帮助。 @Prientus
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多