skip to Main Content

I’ve been studying swift for 2 days, and I have a problem:(

I have two ViewControllers and I need to call a func in the first from the second.

E.g. I want to add one to variable c in the first ViewController from the second:

class FirstViewController: UIViewController {

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

      var c = 0
      func c_count() {
            c += 1
      }
}
class SecondViewController: UIViewController {

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

      @IBAction func button(_sender: Any) {
            //call c_count()
      }
}

I tried to use:

@IBAction func button(_sender: Any) {
      let vc = FirstViewController()
      vc.c_count()
}

but it said ‘Thread 1: breakpoint 1.1 (1)’

2

Answers


  1. Welcome to SO, and to Swift!

    Your approach can’t work because a fresh instance won’t have the real data. Every time you instantiate a new FirstViewController, c will be set to 0. The instance of FVC that you want is the one that’s in the view hierarchy, so even if you didn’t get that breakpoint message, c would not be updated in the UI.

    There are many ways to overcome this problem, and the one that works best will depend on the specific needs of your program. Here are a few possibilities:

    1. If the view controllers are nested, you can use the responder chain to allow the appropriate VC to capture the IBAction message, even if it’s triggered from a child view.
    2. Save the FirstViewController instance to a variable where SecondViewController can reach it. For example, you could save a weak pointer to FVC into a delegate variable on SVC and formalize the relationship using a protocol.
    3. Factor out the variable into some other object (either a parent of both VCs or a singleton)
    4. Access your instantiated VC via the view hierarchy and call the method directly
    5. Use notifications to send a message which will run the function

    Given you’re new, I’d guess you want either 1 or 2. The last two can be fragile and difficult to debug, so should only be attempted if a simpler approach isn’t possible.

    Login or Signup to reply.
  2. you can create a DataSource class that adopts the necessary protocol. Here’s a basic example:

    class MyDataSource: SomeProtocol{
       
        func doSomething(with parameter1: Int, and parameter2: String) {
            // Perform some action using the parameters or if you want to return a value
        }
    }
    

    In each of your UIViewControllers, create an instance of MyDataSource

    class ViewController1: UIViewController {
        let dataSource = MyDataSource()
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
        func performAction() {
            dataSource.doSomething(with: 10, and: "Hello")
        }
    }
    
    class ViewController2: UIViewController {
        let dataSource = MyDataSource()
        
        override func viewDidLoad() {
            super.viewDidLoad()
        
        }
        
        func performAction() {
            dataSource.doSomething(with: 20, and: "World")
        }
     
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search