Overriding method with selector 'touchesBegan:withEvent:' has incompatible type '(NSSet, UIEvent) -> ()'
Asked Answered
S

9

79

Xcode 6.3. Within a class implementing UITextFieldDelegate protocol, I would like to override touchesBegan() method to possibly hide the keyboard. If I avoid a compiler error in the function spec, then there is a complier error trying to read the "touch" from the Set or NSSet, or else the super.touchesBegan(touches , withEvent:event) throws an error. One of these combinations compiled in Xcode 6.2! (So where is documentation to Swift "Set" and how to get an element from one?)

 override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { 
    // Hiding the Keyboard when the User Taps the Background
        if let touch =  touches.anyObject() as? UITouch {
            if nameTF.isFirstResponder() && touch.view != nameTF {
                nameTF.resignFirstResponder();
            }
        }
        super.touchesBegan(touches , withEvent:event)
    }

Try:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) or
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) 

Compiler error: Overriding method with selector 'touchesBegan:withEvent:' has incompatible type '(NSSet, UIEvent) -> ()' and

super.touchesBegan(touches , withEvent:event)

also complains

'NSSet' is not implicitly convertible to 'Set'; did you mean to use 'as' to explicitly convert?

Try:

override func touchesBegan(touches: Set<AnyObject>, withEvent event: UIEvent) 

Compiler error: Type 'AnyObject' does not conform to protocol 'Hashable'

Try:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 

Compiler error at

if let touch = touches.anyObject() as? UITouch 

'Set' does not have a member named 'anyObject' BUT the function spec and call to super() are OK!

Try:

override func touchesBegan(touches: NSSet<AnyObject>, withEvent event: UIEvent) -> () or
override func touchesBegan(touches: NSSet<NSObject>, withEvent event: UIEvent) 

Compiler error: Cannot specialize non-generic type 'NSSet'

Skink answered 27/2, 2015 at 18:30 Comment(0)
P
161

Swift 1.2 (Xcode 6.3) introduced a native Set type that bridges with NSSet. This is mentioned in the Swift blog and in the Xcode 6.3 release notes, but apparently not yet added to the official documentation (update: As Ahmad Ghadiri noted, it is documented now).

The UIResponder method is now declared as

func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent)

and you can override it like this:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    if let touch = touches.first as? UITouch {
        // ...
    }
    super.touchesBegan(touches , withEvent:event)
}

Update for Swift 2 (Xcode 7): (Compare Override func error in Swift 2)

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if let touch = touches.first {
        // ...
    }
    super.touchesBegan(touches, withEvent:event)
}

Update for Swift 3:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        // ...
    }
    super.touchesBegan(touches, with: event)
}
Panocha answered 27/2, 2015 at 18:46 Comment(6)
Thanks Martin R, All I had to do was change my NSSet to Set<NSObject> and my code is functioning.Risorgimento
Hi @Martin Why super.touchesBegan(touches , withEvent:event) is need? I am still not understand Swift very well.Inscription
I feel like it needs to be this: super.touchesBegan(touches, withEvent:event!) for xCode 7.2Gantrisin
@EugeneGordin: Why do you think so? The last method still compiles with Xcode 7.2.Panocha
it was complaining for me...value of optional type not unwrappedGantrisin
@ZigiiWong because it's the superclass that eventually communicates/transfer the touch, event and makes the UI change. Things won't be managed properly....Apparitor
C
10

With xCode 7 and swift 2.0, use following code:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch =  touches.first{
        print("\(touch)")
    }
    super.touchesBegan(touches, withEvent: event)
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
        print("\(touch)")
    }
    super.touchesEnded(touches, withEvent: event)
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
        print("\(touch)")
    }
    super.touchesMoved(touches, withEvent: event)
}
Cauley answered 14/10, 2015 at 14:57 Comment(2)
I can't build the project. Getting error Method does not override any method from its superclass for the touchesBegan function. I tried to subclass from UIGestureRecognizer and UTapGestureRecognizer. Xcode 7.1Damson
use this #30892754 to check what going on with your codeCauley
M
10

Using Swift 3 and Xcode 8

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

}

override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
// Don't forget to add "?" after Set<UITouch>
}
Mahoney answered 20/9, 2016 at 17:26 Comment(0)
A
6

It is now in the Apple API reference here and for overriding in xCode version 6.3 and swift 1.2 you can use this code:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    if let touch =  touches.first as? UITouch {
         // ...
    }
    // ...
}
Adularia answered 9/4, 2015 at 21:37 Comment(1)
Interesting that the online docs are correct but the version included in the Xcode help system is out-of-date. I guess I need to get in the habit of searching for this stuff online.Shadrach
J
6

The current one right now for the newest update as of xCode 7.2 Swift 2.1 on Dec 19, 2015.

Next time you get an error like this again, remove the function and start typing it again "touchesBe..." and xCode should automatically complete it to the newest one for you instead of trying to fix the old one.

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    for touch: AnyObject! in touches {
        let touchLocation = touch.locationInNode(self)

        //Use touchLocation for example: button.containsPoint(touchLocation) meaning the user has pressed the button.
    }
}
Jamaaljamaica answered 20/9, 2015 at 1:38 Comment(0)
C
4

What worked for me was:

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        if let touch = touches.first as? UITouch {
            // ...
        }

        super.touchesBegan(touches , withEvent:event!)
    }
Clotildecloture answered 8/4, 2015 at 22:10 Comment(2)
If you are on Xcode 6.3 and Swift 1.2 your code will not work. This post if referencing Xcode 6.3 and Swift 1.2.Risorgimento
You are right, I updated Xcode today and it immediately gave error.Clotildecloture
S
4

Small addition. For swift to compile w/o error, you need to add

import UIKit.UIGestureRecognizerSubclass

Solicitude answered 8/5, 2016 at 0:19 Comment(0)
F
1

Using Swift 4 and Xcode 9

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

}
Fearless answered 2/8, 2018 at 19:12 Comment(0)
B
1
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        if let touch = touches.first as? UITouch {

            if touch.view == self.view{
                self.dismiss(animated: true, completion: nil)
            }
        }
    }
Buber answered 3/12, 2019 at 7:24 Comment(1)
Add comments, explain your answer, read how to answer.Perbunan

© 2022 - 2024 — McMap. All rights reserved.