I have a subclassed node called LocationNode, where touch is enabled. It looks like this.
class LocationNode: SKSpriteNode, CustomNodeEvents {
func didMoveToScene() {
self.isUserInteractionEnabled = true
}
}
I haven't overriden touchesBegan in this subclass file, because I want to control all touch events like this in the actual scene file:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchLocation = touches.first!.location(in: self)
let touchedNode = self.atPoint(touchLocation)
//if touchedNode.name != nil {
print("touched")
//}
}
When I try do this, however, it doesn't work. How can I control touch events for a subclassed node in the scene file?
EDIT:
Here's what my override function looks like in the scene.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchLocation = touches.first!.location(in: self)
let touchedNode = self.atPoint(touchLocation)
print("TOUCHED")
}
You could implement this code below in your custom class, in this case LocationNode, to have a "return of touches" to the parent class, then you can handle the touches in both places (also to the main scene) :
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
print("touched!")
}
guard let parent = self.parent else { return }
parent.touchesBegan(touches, with: event)
}
I would like to make "aware" SKSpriteNode aware that touch is outside the node.(for example changing color)
I would like to use tuochesMoved (out of node) if it is possible
I don't want to connect them in any other way.
Those spries should be independend.
How to do that?
Thank you
Obviously you can implement the touchesBegan method to handle touches events :
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
// ...
}
super.touchesBegan(touches, with: event)
}
And the other events to handle touches with the current Swift 3 syntax are:
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>
}
About this, if you don't want to subclass your SKSpriteNode to add useful properties, you can use the userData property to store information about other nodes or himself and also about the current context:
yourSprite.userData = NSMutableDictionary()
yourSprite.userData?.setValue(SKColor.blue, forKeyPath: "currentColor")
yourSprite.userData?.setValue(true, forKeyPath: "selected")
I'm trying to update multiple images upon clicking and dragging over the elements. I've implemented touchesbegan, touchesmoved, and touchesended, but I don't know how to make touchesmoved effect multiple images.
I've been scouring the web, but I haven't been able to find any guides on this. If you could point me in the right direction, or provide me with some basic advice, that would be greatly appreciated.
The following is an example image:
Edit: The following is an example image of what should be possible:
What it should look like.
I'd like to be able to effect the other letters in the same way through the same press, changing their pictures. These pictures are temporary images.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
print("touches began:\(touches)")
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.image = UIImage(named: "slot")!
print("touches moved:\(touches)")
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.image = UIImage(named: "tile")!
print("touches ended")
}
If I understood you correctly, that should be something like this:
class ChangableView: UIView {
private var touchedImageView: UIImageView? {
didSet {
if oldValue == touchedImageView { return }
if let oldValue = oldValue {
oldValue.image = UIImage(named: "tile")!
}
if let newValue = touchedImageView {
newValue.image = UIImage(named: "slot")!
}
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let touch = touches.first else { return }
updateTouchedImageViewWithTouch(touch, event: event)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let touch = touches.first else { return }
updateTouchedImageViewWithTouch(touch, event: event)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
touchedImageView = nil
}
}
private extension ChangableView {
func updateTouchedImageViewWithTouch(touch: UITouch, event: UIEvent?) {
let touchPoint = touch.locationInView(self)
let touchedView = self.hitTest(touchPoint, withEvent: event)
touchedImageView = touchedView as? UIImageView
}
}
In addition your UIViewController should have as view a subclass of ChangableView and do not forget to set userInteractionEnabled property to all the UIImageViews to YES.
I'm trying to create a new override func when i got this error: Method does not override any method from it's superclass
I have already tried to delete the override part but that only gives me another error.
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
let touch : UITouch! = touches.anyObject() as! UITouch
location = touch.locationInView(self.view)
person.center = location
}
override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
let touch : UITouch! = touches.anyObject() as! UITouch
location = touch.locationInView(self.view)
person.center = location
}
The correct method signatures are:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
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'
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)
}
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)
}
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>
}
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 {
// ...
}
// ...
}
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.
}
}
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!)
}
Small addition. For swift to compile w/o error, you need to add
import UIKit.UIGestureRecognizerSubclass
Using Swift 4 and Xcode 9
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
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)
}
}
}