Track fingers in UIViewController - swift

I want to track down the position of my fingers in a UIViewController. I implemented this with the following function and this is working great!
override func viewDidLoad() {
view.userInteractionEnabled = true
view.multipleTouchEnabled = true
super.viewDidLoad()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
//Create subview and place it under your finger.
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
//Here methods which tracks the moves of the finger and updates the subviews position.
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
//Remove subview from superview overhere.
}
I have two issues:
When I press more than 5 fingers on the screen, touchesBegin/touchesMoved/touchesEnded will not be called anymore. Even when I place 6 fingers and remove 1.
Sometimes touchesBegan is called from random positions on my screen. TouchesEnded is called for the same point after that.
Should I implement this on another way? I also tried it using UIGestureRecognizer but without success.
I added this function
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
}
And this is called when I tap the 6th finger on the screen.

Related

The keyboard does not close when I tap on the screen

I am implementing keyboard close as follows but it doesn't work.
extension SleepDiaryViewController: UITextFieldDelegate {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
view.endEditing(true)
}
}
Any ideas why this isn't working?

SKSpriteNode chain

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")

Override function with sprite kit game

I am migrating my game from swift 1 and I can't figure out how to fix this function. I am trying to detect if no touches are taking place, which should keep the ball still. this is the code i have and keep getting error Invalid redeclaration of touchesBegan. Im not sure how to work around this, I've been stuck for a while and can't get the ball to stop moving when no touches present. Please help, thanks
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
// do nothing if ad is showing
if Ad.share().showing {
return
}
let touch = touches.first! as UITouch
let touchedLocation = touch.locationInNode(self)
// change the speedXFirst of the ball if it starts
if start {
// start move
let moveRight = touchedLocation.x > CGRectGetMidX(self.frame)
let speedX = moveRight ? ballSpeedX : -ballSpeedX
ball.speedXFirst = speedX
}
// start game if it stops
else {
startGame()
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //error RIGHT HERE
if start {
// stop move
ball.speedXFirst = 0
}
If you ball must be stopped when the user detaches the finger from the screen, probably you want to use:
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
or this if you need to know when the touches were interrupted:
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
}

Move skspriteNode on swipe actions

What I want to do is making a SkspiteNode move from left to right and back. This happens on touch.
I have this code:
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches{
touchLocation = touch.locationInNode(self)
mainGuy.position.x = touchLocation.x;
}
}
This works. But when I have/move my finger at the right side of the screen and the mainGuy is at the left side of the screen it moves to my finger. This is not what I want to happen.
When I move my finger over the screen it needs to 'follow' my finger from the current position of the mainGuy.
How can I do this?
Do something like:
var touchesBeganPosition: CGPoint?
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
touchesBeganPosition = touches.first?.locationInNode(self)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
touchLocation = touch.locationInNode(self)
if let touchesBeganPosition = touchesBeganPosition {
mainGuy.position.x = touchLocation.x - touchesBeganPosition.x
}
}
}
This is untested of of course, but should be enough to get the general idea.

It says method does not overide any method from its super class, what do i do? [duplicate]

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)
}
}
}