1

I was wondering how I could run a method from another class. For example, something like the following code:

let newVC: ScoreViewController = ScoreViewController()
newVC.makeScore()

The above code won't work for me because in makeScore(), I am changing a label's text, which I can't do with the above code because it is creating a new instance. Is there a way to call a method to be run without creating a new instance so that I can change a label's text in makeScore()?

EDIT:

How ScoreViewController is added to PageViewController:

let vc = storyboard.instantiateViewControllerWithIdentifier("Score") as! ScoreViewController
self.addChildViewController(vc)
self.scrollView.addSubview(vc.view)
smecperson
  • 301
  • 1
  • 4
  • 15
  • How are your controllers connected ? Navigation controller, tabbar controller ? Custom segue ? You need to get the instance to that controller , to properly acces the methods – Dejan Skledar Apr 22 '15 at 05:46
  • All of my controllers are in a scrollView. I can't make a new instance of the view controller. – smecperson Apr 22 '15 at 05:47
  • Can you add a screenshot of the storyboard? – Dejan Skledar Apr 22 '15 at 05:49
  • It's not going to help. All the view controllers are not connected in the storyboard at all. There is PageViewController with a ScrollView in it, FirstViewController, and ScoreViewController. In PageViewController's code, I add the FirstViewController and ScoreViewController to the ScrollView's subview. – smecperson Apr 22 '15 at 05:53
  • It would be very helpfull, to know how the hearchy is in image. – Dejan Skledar Apr 22 '15 at 05:57
  • Show the code about how you add ScoreViewController into your PageViewController – Leo Apr 22 '15 at 06:38
  • Updated the code into the question – smecperson Apr 22 '15 at 06:43

2 Answers2

1

I am assuming that you've some method in your FirstViewController where you're changing the score and showing it in your ScoreViewController. The delegation pattern is the possible solution for this problem. In your FirstViewController create a protocol for updating score such as:

protocol FirstVCScoreDelegate:NSObjectProtocol {

    func makeScore()
}

Then inside your FirstViewController create a var for this delegate:

var delegate: FirstVCScoreDelegate

Then in your PageViewController, where you are creating the instances of the FirstViewController and ScoreViewController, set the delegate of the FirstViewController to ScoreViewController:

var firstVC: FirstViewController()
var scoreVC: ScoreViewController()
firstVC.delegate = scoreVC

And after this, in your method in the FirstViewController where the score is changing:

@IBAction func scoreChangeAction(sender: AnyObject) {

        if delegate.respondsToSelector(Selector("makeScore")) {

            delegate.makeScore()
        }
    }

This will signal the ScoreViewController to update the score. You now have to implement the delegate method inside ScoreViewController:

extension ScoreViewController: ScoreDelegate {

    func makeScore() {
        //update your label
    }
}

I believe this will solve your problem.

UPDATE

Try this in your PageViewController's viewDidLoad: method:

override func viewDidLoad() {
        super.viewDidLoad()

        let mainStoryboard = UIStoryboard(name: "MainStoryboard", bundle: NSBundle.mainBundle())

        let firstVC : FirstViewController = mainStoryboard.instantiateViewControllerWithIdentifier("firstVC") as FirstViewController

        let scoreVC : ScoreViewController = mainStoryboard.instantiateViewControllerWithIdentifier("scoreVC") as ScoreViewController

        firstVC.delegate = scoreVC

        self.addChildViewController(firstVC)
        self.addChildViewController(scoreVC)

        self.scrollView.addSubview(firstVC.view)
        self.scrollView.addSubview(firstVC.view)
    }
Shabib
  • 1,697
  • 4
  • 20
  • 39
0

In the PageViewController, declare a property:

class PageViewController {
    var scoreViewController:ScoreViewController
    // ....
 }

After initializing the ScoreViewController:

let vc = storyboard.instantiateViewControllerWithIdentifier("Score") as! ScoreViewController

Hold it as a property:

self.scoreViewController = vc

Then use

self.scoreViewController.makeScore()
ljk321
  • 16,242
  • 7
  • 48
  • 60
  • I get an error on the last two lines: `'FirstViewController' does not have a member named 'ScoreViewController'`. Was I supposed to do something else? – smecperson Apr 22 '15 at 06:56
  • @Smecla Well, before you assign a property, of course you should declare it in the class. – ljk321 Apr 22 '15 at 06:59
  • When I insert that line, class `PageViewController` displays the following error: `Class 'PageviewController' has no initializers` – smecperson Apr 22 '15 at 07:07
  • If you don't need initializer, just use `var scoreViewController:ScoreViewController?` to make it an optional. And use `self.scoreViewController!.makeScore()` to call it. – ljk321 Apr 22 '15 at 07:14
  • I'm not sure which version of Xcode you are using. Maybe you can try `self.scoreViewController?.makeScore()`, or use `let ` to unwrap it. This kind of errors are trivial and easy to fix. – ljk321 Apr 22 '15 at 07:36
  • Yes, that's it. I fixed it by changing the three lines to `PageViewController().delegate = ScoreViewController()`. It ran! But it still gives the same error as the beginning: `fatal error: unexpectedly found nil while unwrapping an Optional value` – smecperson Apr 22 '15 at 07:45
  • It should be solved be making it optional `var scoreViewController:ScoreViewController?` . Did you add the question mark at the end? – ljk321 Apr 22 '15 at 07:48
  • Yes, I did add that in – smecperson Apr 22 '15 at 07:50