-1

There are multiple questions along these lines on Stack Overflow, but none seem to simply answer my specific question. I would like to be able to create a label on one view controller that can change what it displays based on the value of a label on another view controller. I am using Xcode 8.2.1 and Swift 3.

Edit

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

            }
        }
    }
}

SecondViewController

@IBOutlet weak var billLabel: UILabel!

var billString = "test"

override func viewDidLoad() {
    super.viewDidLoad()

    billLabel.text = billString

}
aequinox
  • 125
  • 1
  • 17
  • Can you be more specific on this? I'm sure you can do it with prepareForSegue, but still... you should put a little more context on this. – i6x86 Feb 08 '17 at 23:19
  • @i6x86 -- I'm a fairly new programmer, so I'm not sure how much more information I can give... There is a label on the second view controller that I want to change the value of based on the value of a label on the first view controller. – aequinox Feb 09 '17 at 00:37
  • What type of data you are displaying on that label, is it a string or int? – i6x86 Feb 09 '17 at 00:48
  • @i6x86 both labels contain strings. – aequinox Feb 09 '17 at 00:50
  • that is __instance__ variable and you try to access to it on __class__ level. no wonder the compiler does not get you at all; maybe `viewController.billString = ...` or something like that would look syntactically correct here, but you are gracefully ignoring defining the types, it seems you try to assign a `UILabel` instance to a `String`... so much ambiguity here, it is hard to tell actually what you'd want doing here. – holex Feb 09 '17 at 14:54
  • @holex how would you suggest I fix that? – aequinox Feb 09 '17 at 14:57
  • I have written all the possible suggestions above. – holex Feb 09 '17 at 15:00
  • @holex I'm a very new swift programmer so I'm not sure how to implement what you are saying. If you could expound on it a little bit that would be very helpful. – aequinox Feb 09 '17 at 15:27
  • The answer was available on this Stack Overflow Page: http://stackoverflow.com/questions/26195262/how-to-create-a-global-variable – aequinox Feb 09 '17 at 20:02

2 Answers2

0

Here is an implementation I was able to hammer out on a Playground super quick. The idea is that you create a protocol and subclass UILabel and override its text property with a didSet that calls the protocol method.

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 now contains the text "Hello World"

You can adapt this to a UIViewController implementation using storyboardIDs or some way to keep track of the ViewControllers and assuming you know the nil state of your UIViewController, you can set the delegate properly.

Prientus
  • 733
  • 6
  • 15
  • Thanks for the help. I'm a fairly new programmer -- where would I put this code in my view controller. Under viewDidLoad? Also -- I don't want to make the labels have an equal value but I do want the first to affect the second. @Prientus – aequinox Feb 09 '17 at 00:36
  • @AEquinox01 Well, I would put the UILabel subclass and the protocol into a new file. Then in the storyboard I would give the label my custom class in the identity inspector tab on the right. Then create the label outlet in ViewControllerA so it recognizes its of "Label" class and then I would put the delegate `self.mylabel.delegate` in viewDidLoad, yes. After that, when you implement the `valueChanged` method in ViewControllerB, you don't have to set it to the incoming text. You can set it to whatever you want. – Prientus Feb 09 '17 at 15:38
  • PS: I updated the code to look more relevant to the ViewController Scheme – Prientus Feb 09 '17 at 15:46
  • I was able to figure it out another way. Thanks for your help. @Prientus – aequinox Feb 09 '17 at 19:59
0

You can implement 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 
               }
            }
        }
    }

You create newVarContainigString in the DestinationViewController and give the segue the name you want and put it where it says yourSegueIDHere and when you perform the segue your var in the destination vc will have the value you send it.

I'm on the phone right so I can't be 100% sure if this code works, but if you have problems you can ask.

i6x86
  • 1,557
  • 6
  • 23
  • 42