I have two view controllers. I also have a universal variable called number. The first view controller has a label on it called mainLabel. My second view controller has a button on it. When the button is pressed it should subtract 200 from the variable number then update the mainLabel label. I can not figure out how to make mainLabel a label that works on the second view controller too.
First View Controller
import UIKit
var number:Int = 0
class ViewController: UIViewController {
#IBOutlet weak var mainLabel: UILabel!
#IBAction func backgroundButton(sender: AnyObject) {
number = number + 1
mainLabel.text = "\(number)"
NSUserDefaults.standardUserDefaults().setObject(number, forKey: "number")
}
override func viewDidLoad() {
super.viewDidLoad()
if NSUserDefaults.standardUserDefaults().objectForKey("number") != nil {
number = NSUserDefaults.standardUserDefaults().objectForKey("number") as! Int
}
mainLabel.text = "\(number)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Second View Controller
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var buy1Label: UILabel!
#IBAction func buy1(sender: AnyObject) {
number = number - 200
buy1Label.text = "Bought!"
mainLabel.text = "\(number)"
}
}
class ViewController: UIViewController {
#IBOutlet weak var mainLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
NSNotificationCenter.defaultCenter().addObserverForName("NSNotificationName", object: nil, queue: nil) { (note) -> Void in
// Number changed, update your UILabel.
var number: Int = NSUserDefaults.standardUserDefaults().integerForKey("keyOfNumber")
self.mainLabel.text = "\(number)"
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func subtractNumberBy200() {
var number: Int = NSUserDefaults.standardUserDefaults().integerForKey("keyOfNumber")
number -= 200
NSUserDefaults.standardUserDefaults().setInteger(number, forKey: "keyOfNumber")
}
}
Hope this will works for you.
Wow, this question cuts to the core of what I have to deal with every day. Here is my first take on how to do this with notifications.
First, setup some common global things.
let NumberDidChangeNote = "NumberDidChangeNote" // A name for the notification.
// A function to get the value of number the same way every time.
func number() -> Int {
return NSUserDefaults.standardUserDefaults().integerForKey("number");
}
// A function to set the value of number the same way every time.
func setNumber(number: Int) {
NSUserDefaults.standardUserDefaults().setInteger(number, forKey: "number")
NSUserDefaults.standardUserDefaults().synchronize()
// Post a number did change notification
NSNotificationCenter.defaultCenter().postNotificationName(NumberDidChangeNote, object: nil)
}
The first view controller splits the roles of setting number and setting the label.
class ViewController: UIViewController {
#IBOutlet weak var mainLabel: UILabel!
#IBAction func backgroundButton(sender: AnyObject) {
setNumber(number() + 1)
}
dynamic func numberDidChange(note: NSNotification) {
mainLabel.text = "\(number())"
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Add an observer which will call numberDidChange() anytime the number changes.
let center = NSNotificationCenter.defaultCenter()
center.addObserver(self, selector: "numberDidChange", name: NumberDidChangeNote, object: nil)
// Fake an initial notification to numberDidChange() to set the initial value of the label.
numberDidChange(NSNotification(name: NumberDidChangeNote, object: nil))
}
override func viewWillDisappear(animated: Bool) {
// Remove the observer when not on the screen.
let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self, name: NumberDidChangeNote, object: nil)
super.viewWillDisappear(animated)
}
}
Now the second view controller doesn't have to worry about the first view controller at all.
class SecondViewController: UIViewController {
#IBOutlet weak var buy1Label: UILabel!
#IBAction func buy1(sender: AnyObject) {
setNumber(number() - 200)
buy1Label.text = "Bought!"
}
}
Related
I am quite new to Swift programming and I am trying to set a slider min, max and value in a NSToolbar. As an hypothetical exemple, I have a list of client and I want to use the slider in the toolbar to select a client data page. I will firt to load the client database in the NSViewController and count the number of client. Than I would like to set the slider in the toolbar minvalue to 1 and maxvalue to the number of client. I understand how to send slider values from the Windowcontroller to the ViewController but I did not found how to do the inverse , how to send data from the Viewcontroller to the Window controller in order to set the slider values.
I have attach an simple code based on this exemple https://github.com/gbdavid2/DavidCodes_macOS/tree/master/NSToolbar%20with%20Storyboards/NSToolbar%20with%20Storyboards
In this exemple, the Toolbar shows a Previous and an Next button that , when clicked, they change a counter value (count). I would like to send back that value from the ViewCoOntroller to the WindowController in order to display it in label and eventually, the slider value in the toolbar. Thanks for your help.
// WindowController.swift
import Cocoa
class WindowController: NSWindowController {
#IBOutlet weak var myBoutton: NSToolbarItem!
var viewController: ViewController {
get {
return self.window!.contentViewController! as! ViewController
}
}
override func windowDidLoad() {
super.windowDidLoad()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
//viewController.myLabel.stringValue = "boo"
}
#IBAction func previous(_ sender: Any) {
viewController.updateMyLabelText(newText: "Prev Button clicked! ")
}
#IBAction func next(_ sender: Any) {
viewController.updateMyLabelText(newText: "Next Button clicked! ")
}
}
import Cocoa
class ViewController: NSViewController {
var count : Int = 0
#IBOutlet weak var myLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func updateMyLabelText(newText: String){
if newText.contains("Prev") {count -= 1}
else if newText.contains("Next") {count += 1}
myLabel.stringValue = newText + String(count)
}
}
Another way to to achieve this is with Cocoa Bindings. Example:
In the toolbar are a Previous button, a Next button and a slider. The actions of the buttons are connected to the First Responder. The action methods are implemented in ViewController. The count property of ViewController has attributes #objc dynamic so it can be used with Cocoa Bindings.
class ViewController: NSViewController {
#objc dynamic var count: Int = 0
#IBAction func previous(_ sender: Any) {
count -= 1
}
#IBAction func next(_ sender: Any) {
count += 1
}
}
The slider in the toolbar is bound to the Window Controller, key path window.contentViewController.count.
In the view is a label with a number formatter. The value of the label is bound to the View Controller, key path count.
The window controller isn't subclassed.
There are multiple ways to achieve this.
One of the way is by creating a class [e.g: SliderManager] which keep tracks of current value and handles increment/decrement. You can get the current value of Slider with the help of Singleton in any Controller.
Here is an example implementation:
protocol SliderCountDelegate: NSObject {
func counterDidUpdate()
}
final class SliderCountManager {
static let shared = SliderCountManager()
var value: UInt8 = 0 // <-- Unsigned Integers: Only Positive numbers
weak var delegate: SliderCountDelegate?
public func increaseCounter() {
value += 1
delegate?.counterDidUpdate()
}
public func decreaseCounter() {
value -= 1
delegate?.counterDidUpdate()
}
}
Here is how you should use this in your code:
// WindowController.swift
import Cocoa
class WindowController: NSWindowController {
#IBOutlet weak var myBoutton: NSToolbarItem!
override func windowDidLoad() {
super.windowDidLoad()
}
#IBAction func previous(_ sender: Any) {
SliderCountManager.shared.increaseCounter()
print(SliderCountManager.shared.value) // <- Accessing Current value here
}
#IBAction func next(_ sender: Any) {
SliderCountManager.shared.decreaseCounter()
print(SliderCountManager.shared.value)
}
}
import Cocoa
class ViewController: NSViewController, SliderCountDelegate {
#IBOutlet weak var myLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
SliderCountManager.shared.delegate = self // Set Delegate to `self`
}
override var representedObject: Any? {
didSet {
}
}
// Protocol conformance
func counterDidUpdate() {
myLabel.stringValue = String(SliderCountManager.shared.value)
}
}
Thanks for the proposed solutions. It certainly put me in the wrigth direction.
Here is what I did. In the WindowController , I set a toolbar with 1) button «previous», 2) button «next» and 3) a slider «slider».
Those are linked to the proper IBOutler and IBaction in the WindowController.
The viewController have a textLabel «myLabel»
The 2 buttons and the slider change the slider_ptr value in the ViewControler and is sent to myLabel. Also, the slider.label change according to the slider_pointer and the slider_max values. Here is the code for the windowController:
import Cocoa
class WindowController: NSWindowController {
#IBOutlet weak var slider: NSSlider!
#IBOutlet weak var sliderTB: NSToolbarItem!
var viewController: ViewController {
get {
return self.window!.contentViewController! as! ViewController
}
}
override func windowDidLoad() {
super.windowDidLoad()
setSlider() // set initial value based on ViewController
}
#IBAction func previous(_ sender: Any) {
viewController.previous (WindowController())
setSlider()
}
#IBAction func next(_ sender: Any) {
//viewController.updateMyLabelText(newText: "Prev Button clicked! ")
viewController.next (WindowController()) //send to VC function previous
// let pt = viewController.slider_ptr + 1
//let sMax = viewController.slider_max
setSlider()
//sliderTB.label = String(pt) + " de " + String(sMax)
}
#IBAction func sliderDidChange(_ sender: Any) {
viewController.sliderDidSlide (WindowController(), pointer: Int(slider.doubleValue))
setSlider()
// viewController.sliderDidSlide(PosiWC(), sValue: myslider.doubleValue)
}
func setSlider() {
/* myslider.minValue = 1
myslider.maxValue = Double(max)
myslider.integerValue = pointer*/
//print ("WCP58:" , myslider.integerValue )
let pt = viewController.slider_ptr
let sMax = viewController.slider_max
//slider (max : pt, pointer: sMax)
sliderTB.label = String(pt) + " de " + String(sMax)
slider.minValue = 1
slider.maxValue = Double(sMax)
slider.integerValue = pt
}
}
and for the Viewcontroller :
class ViewController: NSViewController {
var slider_ptr = 1 // slider position
var slider_max: Int = 0 //
#IBOutlet weak var myLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
slider_max = 250
myLabel.stringValue = String(slider_ptr)
}
override var representedObject: Any? {
didSet {
}
}
func previous(_ sender: Any) {
if slider_ptr > 1 {
slider_ptr -= 1
}
else { NSSound.beep()}
myLabel.stringValue = String(slider_ptr)
}
func next(_ sender: Any) {
if slider_ptr < slider_max {
slider_ptr += 1
}
else { NSSound.beep()}
myLabel.stringValue = String(slider_ptr)
}
func sliderDidSlide(_ sender: Any, pointer : Int) {
print (pointer)
slider_ptr = pointer
myLabel.stringValue = String(slider_ptr)
}
}
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 2 years ago.
I am working on a Magic the Gathering Counter app. For my app, I want to click twentyLife(), thirtyLife(), or fourtyLife() to change the value of a variable in another view controller (i.e. FifthViewController.)
Second view controller code:
import UIKit
class SecondViewController: UIViewController {
var vcFive = FifthViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func twentyLife() {
vcFive.lifePoints.text = String(20)
}
#IBAction func thirtyLife() {
vcFive.lifePoints.text = String(20)
}
#IBAction func fortyLife() {
vcFive.lifePoints.text = String(20)
}
I try and call out the fifthViewController as a variable to change my life points text but it does not work.
Here is my code for the fifthViewController:
import UIKit
class FifthViewController: UIViewController {
#IBOutlet weak var lifePoints: UILabel!
var counter = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func lifeUp() {
counter += 1
lifePoints.text = String(counter)
}
#IBAction func lifeDown() {
counter -= 1
lifePoints.text = String(counter)
}
Any help would be appreciated. This is my first app I have been trying to work on from scratch
You should create an instance of your FifthViewController on your SecondViewController, and a variable on your FifthViewController in which you can save the data passed. Like this:
SecondViewController
import UIKit
class SecondViewController: UIViewController {
let fifthVC = self.storyboard?.instantiateViewController(withIdentifier: "fifthVC") as? FifthViewController
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func twentyLife() {
fifthVC.lifePointsInt = 20
}
#IBAction func thirtyLife() {
fifthVC.lifePointsInt = 30
}
#IBAction func fortyLife() {
fifthVC.lifePointsInt = 50
}
}
FifthViewController
import UIKit
class FifthViewController: UIViewController {
var lifePointsInt = Int()
#IBOutlet weak var lifePoints: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
lifePoints.text = "\(lifePointsInt)"
}
#IBAction func lifeUp() {
lifePoints.text = "\(lifePointsInt + 1)"
}
#IBAction func lifeDown() {
lifePoints.text = "\(lifePointsInt - 1)"
}
}
Remember to type in your Storyboard ID in your storyboard for your FifthViewController as "fifthVC" If your pass to your FifthViewController after selecting your Life Count in your SecondViewController you could add self.navigationController?.pushViewController(fifthVC!, animated: true) at the end of each function.
I'm developing a simple game (my first iOS app!) and am trying to link a variable between two View Controllers. In the first view controller, I have a textfield where the user can type in any number they choose. In the second View Controller, I would like users to be able to generate any number between 1 and the number they entered by pressing a button and be able to keep doing so. However, I am not able to use the "upperBound" variable holding the user-entered value in ViewController2.
I've tried using prepare for segue but it's not working, and I've snooped around stackoverflow and tried a couple of methods without quite knowing what I'm doing to no avail.
(UPDATED) ViewController:
class ViewController: UIViewController, UITextFieldDelegate {
//MARK: Properties
#IBOutlet weak var numberOfPages: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Handle the text field’s user input through delegate callbacks.
numberOfPages.delegate = self
}
//MARK: UITextFieldDelegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Hide the keyboard.
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
//Save number entered and then randomly select a number within bounds
}
//MARK: Actions
var upperBound: Int?
#IBAction func setUpperBound(_ sender: UIButton) {
upperBound = Int(numberOfPages.text!)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
// Create a variable that you want to send
var newUpperBound = Int(upperBound!)
// Create a new variable to store the instance of ViewController2
let destinationVC = segue.destination as! ViewController2
destinationVC.upperBound = newUpperBound
}
}
(UPDATED) ViewController2:
class ViewController2: UIViewController, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
//Mark: Actions
#IBAction func roller(_ sender: UIButton) {
//Generate random number
let randomNumber = Int.random(in: 0 ..< upperBound)
}
var upperBound: Int?
}
With this code, I'm getting an error on line 34 of ViewController2 that reads "Use of unresolved identifier upperBound". Additionally, there is an issue on line 40 of ViewController that reads "immutable value upperBound was never used". I would expect to be able to generate a random value between 1 and the entered number so that I can keep working and add more features to my app (like printing these random values etc)
ViewController
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var numberOfPages: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
numberOfPages.delegate = self
}
//MARK: UITextFieldDelegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Hide the keyboard.
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
//Save number entered and then randomly select a number within bounds
}
//MARK: Actions
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if numberOfPages.text == ""{
print("Please enter number")
return
}
let upperBound: Int? = Int(numberOfPages.text ?? "0")
if upperBound != 0{
if segue.identifier == "mySegue"{
let vc = segue.destination as! ViewController2
vc.upperBound = upperBound
}
}
}
}
ViewController2
import UIKit
class ViewController2: UIViewController {
#IBOutlet weak var lbl_UpperBound: UILabel!
#IBOutlet weak var btn_Generate: UIButton!
#IBOutlet weak var lbl_Random: UILabel!
var upperBound: Int?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
lbl_UpperBound.text = "Upper Bound - \(upperBound ?? 0)"
btn_Generate.addTarget(self, action: #selector(roller), for: .touchUpInside)
lbl_Random.text = ""
}
#objc func roller(_ sender: UIButton) {
//Generate random number
let randomNumber = Int.random(in: 0 ..< (upperBound ?? 1))
lbl_Random.text = "\(randomNumber)"
}
}
Also Don't forget to name the Segue
This is the error Xcode outputs
Unexpectedly found nil while unwrapping an Optional value
I have a viewcontroller that has a tableview and a few buttons; the buttons allow me to insert or remove data. It seems that when I click on Add (which brings up a new viewcontroller via segue as a sheet) the app crashes with the error above. Clicking on remove doesn't have this affect. So it has to do with something regarding the new viewcontroller as a guess. The console doesn't go further into the error other than printing out (lldb)
Here's my code
override func viewDidLoad() {
super.viewDidLoad()
alarmTableView.dataSource = self //error occurs here
alarmTableView.delegate = self //if i remove the above line if will occur here too.
}
My Viewcontroller which the above viewDidLoad func is embedded lists the protocols I need
class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet weak var addAlarm: NSButton!
#IBOutlet weak var resetDataButton: NSButton!
#IBOutlet var alarmArrayController: NSArrayController!
#IBOutlet weak var alarmTableView: NSTableView!
#IBOutlet weak var deleteAll: NSButton!
#objc let moc: NSManagedObjectContext
required init?(coder: NSCoder) {
self.moc = CoreDataHandler.getContext()
super.init(coder: coder)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
let destinationController = segue.destinationController as! AddAlarmViewController
//pass data to next controller here
}
#IBAction func deleteAllAction(_ sender: Any) {
if (alarmTableView.selectedRow >= 0) {
if (CoreDataHandler.deleteAllObjectsInEntity(entityName: "Alarm")) {
//remove from nsarray controller
for object in alarmArrayController.arrangedObjects as! [Alarm] {
print(object)
alarmArrayController.removeObject(object)
}
alarmTableView.reloadData()
}
}
else {
printInfo(str: "There are no alarms to delete")
}
}
/* Response to the remove alarm button - It removes a selected alarm object from the table */
#IBAction func resetDataAction(_ sender: Any) {
if (alarmTableView.selectedRow >= 0) {
let selectedAlarm = self.alarmArrayController.selectedObjects.first as! Alarm
alarmArrayController.remove(atArrangedObjectIndex: alarmTableView.selectedRow)
CoreDataHandler.deleteObjectInEntity(entityName: "Alarm", obj: selectedAlarm)
alarmTableView.reloadData()
}
else {
//will need a warning or play a sound.
printInfo(str: "Please select an alarm")
}
}
override func viewDidLoad() {
super.viewDidLoad()
printInfo(str: "viewdidload")
print(alarmTableView)
if (alarmTableView != nil) {
printInfo(str: "AlarmTableView Is initialised")
alarmTableView.dataSource = self
alarmTableView.delegate = self
}
else {
printInfo(str: "AlarmTableView is not initialised")
}
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func printInfo(str: String) {
print("ViewController: \(str)")
}
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
return 100.0
}
}
class AddAlarmViewController: ViewController {
#IBOutlet weak var closeButton: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
printClassInfo(str: "viewDidLoad")
CoreDataHandler.saveTestData()
}
#IBAction func closeButtonAction(_ sender: Any) {
self.dismissViewController(self)
}
func printClassInfo(str: String) {
print("AddAlarmViewController \(str)")
}
}
If I remove the lines where the error occurs the app run fine. But I want to override the delegate and datasource and use the functions to further customise the table. I'm also using Cocoa Bindings.
Why am I getting this error?
Update
I haven't solved it yet, but i placed a couple of print statements in my viewDidLoad function. It seems that when the app is first loaded, the table view is initialised. But after when I clicked on the Add button, the table view is then set to nil for some odd reason, as if another table view has been initialised. However the data is still visible
Problem:
class AddAlarmViewController: ViewController {
//...
override func viewDidLoad() {
super.viewDidLoad()
//...
}
}
Your AddAlarmViewController is a subclass of ViewController instead of NSViewController.
In AddAlarmViewController's viewDidLoad you call super.viewDidLoad() which basically calls ViewController's viewDidLoad.
But... in this case ViewController is a new instance as the super class of AddAlarmViewController and none of it's properties are initialized.
Whatever it be, it's probably not what you want.
Solution:
class AddAlarmViewController: NSViewController {
//... rest as it is
}
I have a view controller embedded in another VC.
I would like to get the value of a variable from the main VC inside the embedded one. Specifically, I would like to change the text of label2 based on the value of label1.
I tried with "prepareForSegue", but it seems it's not triggered for embedded view controllers. I tried to isolate the problem in a test project:
Code for main VC:
class MyViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Hello"
}
}
Code for embedded VC:
class EmbeddedVC: UIViewController {
#IBOutlet weak var label2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Thanks for your help :)
A way to achiеve this is to get the child view controller instance in the parent's viewDidLoad. It appears that the parent's viewDidLoad: gets called after the child's viewDidLoad:, which means the label is already created in the child's view.
override func viewDidLoad() {
super.viewDidLoad()
if let childVC = self.childViewControllers.first as? ChildVC {
childVC.someLabel.text = "I'm here. Aye-aye."
}
}
First of all you can't set directly EmbeddedVC's lable2.text In prepareForSegue
because call sequence following below
MainVC's prepareForSeque this time EmbeddedVC's label2 is nil
EmbeddedVC's viewDidLoad called then label2 loaded
MainVC's viewDidLoad called then label1 loaded
so if you assign MainVC's label1.text to EmbeddedVC's label2.text in prepareForSeque
both label1 and label2 are nil so did not work
There are two way to solve this question
First Solution
MainViewController has EmbeddedVC and when MainVC's viewDidLoad called, assign label1.text to embeddedVC.label2.text
class MyViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
var embeddedVC: EmbeddedViewController? = nil
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Hello"
embeddedVC?.label2.text = label1.text
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let embeddedVC = segue.destination as? EmbeddedViewController {
self.embeddedVC = embeddedVC
}
}
}
class EmbeddedViewController: UIViewController {
#IBOutlet weak var label2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Second Solution, use protocol and get MainVC's label text when viewWillAppear or viewDidAppear (later viewDidLoad called)
protocol EmbeddedVCDelegate: class {
func labelText() -> String?
}
class MyViewController: UIViewController, EmbeddedVCDelegate {
#IBOutlet weak var label1: UILabel!
// MARK: EmbeddedVCDelegate
func labelText() -> String? {
return label1.text
}
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Hello"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let embeddedVC = segue.destination as? EmbeddedViewController {
embeddedVC.delegate = self
}
}
}
class EmbeddedViewController: UIViewController {
#IBOutlet weak var label2: UILabel!
weak var delegate: EmbeddedVCDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
}
override viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
label2.text = delegate?.labelText()
}
}
You should try to use prepareForSegue like this:
if segue.identifier == "identifier" {
guard let destinationViewController = segue.destination as? VC2 else { return }
destinationViewController.label2.text = mytext
}
Where the segue identifier you assign in storyboard