0

I have been working on an app with XCode (in version 9.3.1) and was using the Coding iPhone Apps for Kids (https://nostarch.com/iphoneappsforkids/) as a guide to learn how to create games such as the skateboarder game that begins in chapter 14.

I have followed the code, however, has run into an error with using the handleTap(tapGesture:).

      override func didMove(to view: SKView) {
    physicsWorld.gravity = CGVector(dx: 0.0, dy: -6.0)
    physicsWorld.contactDelegate = self

    anchorPoint = CGPoint.zero

    let background = SKSpriteNode(imageNamed: "background")
    let xMid = frame.midX
    let yMid = frame.midY
    background.position = CGPoint(x: xMid, y: yMid)
    addChild(background)

    setupLabels()

    // Set up the player and add her to the scene
    player.setupPhysicsBody()
    addChild(player)

    // Add a tap gesture recognizer to know when the user tapped the screen
    let tapMethod = #selector(GameScene.handleTap(tapGesture:))
    let tapGesture = UITapGestureRecognizer(target: self, action: tapMethod)
    view.addGestureRecognizer(tapGesture)

    // Add a menu overlay with "Tap to play" text
    let menuBackgroundColor = UIColor.black.withAlphaComponent(0.4)
    let menuLayer = MenuLayer(color: menuBackgroundColor, size: frame.size)
    menuLayer.anchorPoint = CGPoint(x: 0.0, y: 0.0)
    menuLayer.position = CGPoint(x: 0.0, y: 0.0)
    menuLayer.zPosition = 30
    menuLayer.name = "menuLayer"
    menuLayer.display(message: "Tap to play", score: nil)
    addChild(menuLayer)
}

It gives the error in

    let tapMethod = #selector(GameScene.handleTap(tapGesture:))

However, further down, I have this code.

     func handleTap(tapGesture: UITapGestureRecognizer) {

        if gameState == .running {

            // Make the player jump if player taps while she is on the ground
            if player.isOnGround {

                player.physicsBody?.applyImpulse(CGVector(dx: 0.0, dy: 260.0))

                run(SKAction.playSoundFileNamed("jump.wav", waitForCompletion: false))
            }
        }
        else {

            // If the game is not running, tapping starts a new game
            if let menuLayer: SKSpriteNode = childNode(withName: "menuLayer") as? SKSpriteNode {

                menuLayer.removeFromParent()
            }

            startGame()
        }
    }

Though I have handleTap under the update method, the error would not remove itself.

If you have a solution to the error code in the title, please let me know.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Amber
  • 5
  • 2
  • 1
    Sh_Khan has what I believe is the correct response. Btw, side note: the order of methods inside the class does not affect things. What I mean is: `handleTap` and `update` can exist in any order, inside your class. Good luck! – JaredH May 26 '18 at 01:57
  • @JaredH I have attempted the answer and has received more errors. If you have an alternative, it would be helpful! And thanks for explaining that. It did always give me a bit of confusion. – Amber May 26 '18 at 02:13
  • Are you sure that the `handleTap` method is at the top level of the class and not inside some other method? – rmaddy May 26 '18 at 02:15
  • Also, what classes is all of this code in? Is this `didMove` and `handleTap` both in the same class? And is that the `GameScene` class? – rmaddy May 26 '18 at 02:21

2 Answers2

0

Change selector & signature to this

let tapMethod = #selector(GameScene.handleTap(_:))

//

@objc func handleTap(_ tapGesture: UITapGestureRecognizer) {}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • I have attempted this and have received the same error, as well as this for the second line. : @ objc can only be used with members of classes, @objc protocols, and concrete extensions of classes – Amber May 26 '18 at 02:04
  • Create a new empty project and test them you may have a mess somewhere as if GameScene contains the method like this the selector will go without any compile errors – Shehata Gamal May 26 '18 at 02:13
  • There is nothing wrong with the original selector and original method signature other than needing to add `@objc`. While the suggestion in this answer isn't wrong, the original is just as correct. – rmaddy May 26 '18 at 02:16
  • I had rewritten Game scene and found there was an error. Thank you for your assistance! – Amber May 26 '18 at 02:21
0

As per docs,

In Objective-C, a selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure, and can be constructed using the #selector expression. To create a selector for a method that can be called from Objective-C, pass the name of the method

So we have to expose the member to obj-c by mark it as @objc

@objc func handleTap(_ tapGesture: UITapGestureRecognizer) {}

For more information refer: How can I deal with @objc inference deprecation with #selector() in Swift 4?

Lal Krishna
  • 15,485
  • 6
  • 64
  • 84