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'

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
SoCor
  • 803
  • 1
  • 7
  • 6

9 Answers9

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)
}
Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
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)
}
Himanshu Mahajan
  • 4,779
  • 2
  • 36
  • 29
  • 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.1 – Boris Y. Nov 08 '15 at 00:45
  • use this http://stackoverflow.com/questions/30892254/override-func-error-in-swift-2 to check what going on with your code – Himanshu Mahajan Nov 09 '15 at 11:56
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>
}
Chetan Prajapati
  • 2,249
  • 19
  • 24
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 {
         // ...
    }
    // ...
}
Ahmad Ghadiri
  • 311
  • 2
  • 9
  • 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. – Duncan C Apr 26 '15 at 19:50
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.
    }
}
Hedylove
  • 1,724
  • 16
  • 26
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!)
    }
Malloc
  • 15,434
  • 34
  • 105
  • 192
jfredsilva
  • 1,434
  • 1
  • 9
  • 15
4

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

import UIKit.UIGestureRecognizerSubclass

beshio
  • 794
  • 2
  • 7
  • 17
1

Using Swift 4 and Xcode 9

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

}
ammar shahid
  • 411
  • 4
  • 17
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)
            }
        }
    }
Dino
  • 7,779
  • 12
  • 46
  • 85
Talha Rasool
  • 1,126
  • 14
  • 12
  • 2
    Add comments, explain your answer, read [how to answer](https://stackoverflow.com/help/how-to-answer). – Aksen P Dec 03 '19 at 09:28