user3545063
user3545063

Reputation: 811

The best way to call a function inside another class? (Swift)

So, I've got a fairly simple question regarding Classes and Functions in Swift.

Let's say I make an app with SpriteKit. I have a GameScene (SKScene), a GameViewController (UIViewController) and a main storyboard for the GameViewController.

If I wanted to have a button on top of my GameScene, I'd connect a button IBOutlet from the main storyboard to the GameViewController. But how can I set it up, so that if I touch the button I can call a function inside the GameScene?

Do I have to handle this with delegation or is there a simpler method?

EDIT:

To elaborate, the function I'd like to call is:

  func resetScene(){
        self.removeAllActions()
        self.removeAllChildren()
    }

I tried to declared as a class func but somehow it doesn't quite work.

Upvotes: 5

Views: 8072

Answers (3)

Pink
Pink

Reputation: 531

There are basically four ways of calling a function from an other class.

  1. Instance of the class. If you have an instance of say class Object, you can call Object's methods over that instance like myObject.buttonTapped().

  2. By delegation: Create a protocol for class A and declare the method in the protocol. Class A must have an instance of the protocol. Call that method in the buttonTapped method like delegate.notifyButtonTapped(). In class B, conform to the protocol and implement the notifyButtonTapped() method.

  3. Notification: Post a notification over NotificationCenter from class A and addObserver to in class B for that notification. Check this link for further information.

  4. Closure/Blocks: In this case closure is not the best solution and they can be fairly complex to fully understand

You can go with the delegation here. Check this link from rw for clarification.

Upvotes: 5

Alessandro Ornano
Alessandro Ornano

Reputation: 35392

I don't like the way how you reset the SKScene, usually you can present the same scene to have a really cleaned scene, but I don't know your code so maybe I'm wrong.

About to how to access to the viewController of your scene you could find many ways as for example the protocol/delegate method but another one of them could be:

extension UIView {
    func getViewController<T: UIViewController>() -> T? {
        var responder = self.next
        while responder != nil {
            if let viewController = responder as? T {
                return viewController
            }
            responder = responder!.next
        }
        return nil
    }
}

And to use it :

if let gameVC = self.view?.getViewController(), gameVC is GameViewController {
    let vc = gameVC as! GameViewController
    print("That's all folks \(vc)")
}

Upvotes: 4

jnewkirk
jnewkirk

Reputation: 391

Making assumptions here, if your GameViewController contains a reference to your GameScene then you can do this quite easily. You can create an IBAction reference with a given method name buttonTapped. Inside this method you can then call a method on your GameScene that performs the actions you are looking to do

// GameViewController
@IBAction func buttonTapped(sender: UIButton) {
   self.gameScene.reactionMethod()
}

// GameScene
public func reactionMethod() {
   // TODO: Do actions here
}

Upvotes: 0

Related Questions