0

i need to change UIButton(status, title) from another UIViewController

i tried the below

import UIKit

class ViewController: UIViewController{

    @IBOutlet var B1: UIButton!
    @IBOutlet var B2: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
    }


}
import Foundation
import UIKit

class View2: UIViewController {
    @IBAction func Dismiss(_ sender: Any) {
        h()

        dismiss(animated: true, completion: nil)
    }


    func h(){
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "VC") as? ViewController
        vc?.loadViewIfNeeded()

        print("c: ",vc?.B1.currentTitle ?? "")
        vc?.B1.setTitle("a", for: .normal)
        print("c: ",vc?.B1.currentTitle ?? "")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

The Output is :

c:  V1B1
c:  a

it's changed (as the output said) ! but when the view dismissed it goes back to "V1B1" which is the title i put in Main.storyboard

i also tried to change it with protocol and delegate

import UIKit

class ViewController: UIViewController,TestDelegate {
    func t(NewT: UIButton) {
        NewT.setTitle("a", for: .normal)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dd = segue.destination as? View2 {
            dd.d = self
            print("B1O: ",B1.currentTitle!)
        }
    }

    @IBOutlet var B1: UIButton!
    @IBOutlet var B2: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
import Foundation
import UIKit

protocol TestDelegate {
    func t(NewT: UIButton)
}

class View2: UIViewController {
var d: TestDelegate?

    @IBAction func Dismiss(_ sender: Any) {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "VC") as? ViewController
        vc?.loadViewIfNeeded()
        print("B1: ",vc?.B1.currentTitle!)
            d?.t(NewT: (vc?.B1!)!)
        print("B1: ",vc?.B1.currentTitle!)

        dismiss(animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Output:

B1O:  V1B1
B1:  Optional("V1B1")
B1:  Optional("a")

what's wrong with the code ?

How can i change the UIButtons permanently even if the UIViewController loaded again

Bhavesh Nayi
  • 705
  • 4
  • 15
OneOfThem
  • 23
  • 6

3 Answers3

1
import UIKit

class ViewController: UIViewController{

    @IBOutlet var B1: UIButton!
    @IBOutlet var B2: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    open override func viewWillAppear(_ animated: Bool) {
        // Register to receive notification
        NotificationCenter.default.addObserver(self, selector: #selector(self.updateTitle), name: NSNotification.Name(rawValue: "buttonTitleUpdate"), object: nil)
        super.viewWillAppear(animated)
    }

    @objc func updateTitle() -> Void {
        print("c: ",B1.currentTitle ?? "")
        B1.setTitle("a", for: .normal)
        print("c: ",B1.currentTitle ?? "")
    }

}


import Foundation
import UIKit

class View2: UIViewController {
    @IBAction func Dismiss(_ sender: Any) {

        // Post a notification
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "buttonTitleUpdate"), object: nil)

        dismiss(animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
Bhavesh Nayi
  • 705
  • 4
  • 15
0

"it's changed (as the output said) ! but when the view dismissed it goes back to "V1B1" which is the title i put in Main.storyboard"

You've changed the title of B1 in a new instance of V1, not in the existing instance of V1.

Don't create a new instance for ViewController class in the dismiss method

class ViewController: UIViewController,TestDelegate {
    func change(text: String) {
        B1.setTitle(text, for: .normal)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dd = segue.destination as? View2 {
            dd.d = self
            print("B1O: ",B1.currentTitle!)
        }
    }

    @IBOutlet var B1: UIButton!
    @IBOutlet var B2: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
protocol TestDelegate {
    func change(text: String)
}

class View2: UIViewController {
    var d: TestDelegate?

    @IBAction func Dismiss(_ sender: Any) {
        d?.change(text:"NewTitle")
        dismiss(animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
  • the button will be different every time , that's why i thing the protocol should be UIButton rather than a String , i only used tow classes to explain the issue but the project is much more bigger . – OneOfThem May 02 '19 at 07:15
  • @OneOfThem Do you have 2 buttons or more? – RajeshKumar R May 02 '19 at 07:16
  • also , kindly if u can explain what is going wrong with my code – OneOfThem May 02 '19 at 07:16
  • basically , the project is a game and the buttons are levels , once the user finished a level the next level will be available for him "isEnabled = true" – OneOfThem May 02 '19 at 07:18
  • @OneOfThem First you have an instance of ViewController class, let us name it a. Then you perform segue to an instance of View2, let us name it b. Now when you dismiss b you return to a. But you are creating a new instance c for the class ViewController. If you change title of a button in c it won't change the title in a – RajeshKumar R May 02 '19 at 07:19
  • @OneOfThem you should keep a reference to the completed level number and pass the number in the delegate. Update the first view controller based on the passed number – RajeshKumar R May 02 '19 at 07:20
  • @OneOfThem if you use tableview or collection view in first viewcontroller to show all buttons it will be easier to handle this by completed level number – RajeshKumar R May 02 '19 at 07:21
  • Gr8 explanation and thank u for that , i will use tables and collection views in the near future , for now how can i use the same reference every time i call the ViewController ? – OneOfThem May 02 '19 at 07:24
  • @OneOfThem Don't use the reference of ViewController in View2. Pass completed level number in delegate method from View2 to ViewController like 10. In ViewController method update the buttons based on the passed level number – RajeshKumar R May 02 '19 at 07:28
0

many thanks to "RajeshKumar R" and "Bhavesh Nayi"

import UIKit

class ViewController: UIViewController,TestDelegate {
    func t(NewT: Int) {
    let TempButton = self.view.viewWithTag(NewT) as! UIButton
        TempButton.setTitle("X", for: .normal)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dd = segue.destination as? View2 {
            dd.d = self
        }
    }


    @IBOutlet var B1: UIButton!
    @IBOutlet var B2: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
import Foundation
import UIKit

protocol TestDelegate {
    func t(NewT: Int)
}

class View2: UIViewController {
var d: TestDelegate?

    @IBAction func Dismiss(_ sender: Any) {
        //just pass the tag
            d?.t(NewT: 1)
        dismiss(animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}


OneOfThem
  • 23
  • 6