I need to move, rotate and zoom an UIImageView object. In the method...
touchesBegan(NSSet *)touches withEvent:(UIEvent *)event
which touches do I have to use?
(NSSet *)touches
or
event.allTouches
In other words, where are my touches?
touches passed as the parameter are the touches in your view.
event.allTouches contains all the touches of the event, even the one that didn't start in your view.
Don't hesitate to read the Event Handling Guide for iOS in Apple's doc, it is explained with some pictures it will probably help you understand better.
Especially the difference between the touches in the parameters and event.allTouches is described here ;)
Related
I want to detect touches on AppleWatch to get touch location. As we can achieve this behaviour on iPhone app by using following delegate methods:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//Any Logic
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//Any Logic
}
So, i just used these methods on WatchKit but not working;
Any way to achieve this behaviour?
I want to make some logic on the basis of touch location on WatchKit.
Any direction of work will be appreciated.
At the moment (I don't know if things change in the future), there are no touch recognisers like that for WatchKit. You can just respond on taps on buttons or a menu with a selector.
I'm creating a custom control* by subclassing UIControl and overriding the following methods:
- beginTrackingWithTouch:withEvent:
- continueTrackingWithTouch:withEvent:
- endTrackingWithTouch:withEvent:
- cancelTrackingWithEvent:
This control will support multitouch interaction. Specifically, one or two fingers may touch down, drag for some duration, and then touch up, all independently.
My issue comes at the end of these multitouch events, in endTrackingWithTouch:withEvent:. The system calls this method on my control exactly once per multitouch sequence, and it is called on the first touch up that occurs. This means that the second touch, which could still be dragging, will no longer be tracked.
This sequence of actions serves as an example for this phenomenon:
Finger A touches down. beginTracking is called.
Finger A drags around. continueTracking is called repeatedly to update my control.
Finger B touches down. beginTracking is called.
Fingers A and B drag around. continueTracking is called repeatedly to update my control.
Finger B touches up. endTracking is called.
Finger A drags around. No methods are called.
Finger A touches up. No methods are called.
The issue lies in the final three steps in this sequence. The documentation for UIControl says the following of endTrackingWithTouch:withEvent::
Sent to the control when the last touch for the given event completely ends, telling it to stop tracking.
Yet it seems to me that after finger B touches up in step 5, above, the last touch for the given event has not yet completely ended. That last touch is finger A!
*A range slider, if you must ask. But there are already plenty of open source range sliders, you say. Yes, true, but this one will support multitouch and Auto Layout.
I had the same issue in custom control with multitouch.
Because UIControl is subclass of UIView that inherits from UIResponder, so feel free to use:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
methods.
These methods work fine in UIControl subclass.
in my app i'm able to detect a touch by connecting the view to an action touch down event. However, i want to be able to detect that the user lifted his finger off screen. am i able to do that?
Edit: sorry for the short post. actually i have no hint how to do that or even to try to do that!
Well, that depends on where you're trying to track the touch removal. If for example, you're using a button and you've already linked an action to touchDown, you can simply link another action for the buttons control event touch up inside/outside.
If you're interested in tracking that touches ended on the entire screen, you can use -touchesEnded: withEvent:.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
}
I want to achieve a simple task - detect up to 10 touches in a UIView.
Using these:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
It all works great.
Problem is - touchesMoved:: is no more called - if first finger, that touched screen no longer touches screen.
Is it possible to fix it? (so that - while atleast one finger from 10 fingers is still touching screen - touchesMoved:: would be called?
If it is not possible in UIKit, could it be possible in Cocos2d, and how? (some links, function peaces would be really helpful)
You probably just need to set theView.multipleTouchEnabled.
I have a UIView subclass where I handle touches using touchesBegan, touchesMoved, touchesEnded.
I noticed that when I start a touch inside and then drag outside the UIView touchesEnded is not triggered, is there a way to have it called when I'm dragging outside the UIView frame?
Thanks
Use touchesCancelled instead.
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
Pssibly it is calling the - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
Please check UIResponder Class Reference
touchesCancelled:withEvent:
Sent to the receiver when a system event (such as a low-memory
warning) cancels a touch event.
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
Parameters
touches
A set of UITouch instances that represent the touches for the ending phase of the event represented by event. event
An object representing the event to which the touches belong.
Discussion
This method is invoked when the Cocoa Touch framework receives a
system interruption requiring cancellation of the touch event; for
this, it generates a UITouch object with a phase of
UITouchPhaseCancel. The interruption is something that might cause the
application to be no longer active or the view to be removed from the
window
When an object receives a touchesCancelled:withEvent: message it
should clean up any state information that was established in its
touchesBegan:withEvent: implementation.
The default implementation of this method does nothing. However
immediate UIKit subclasses of UIResponder, particularly UIView,
forward the message up the responder chain. To forward the message to
the next responder, send the message to super (the superclass
implementation); do not send the message directly to the next
responder. For example,
[super touchesCancelled:touches withEvent:event];
If you override this method without calling super (a common use
pattern), you must also override the other methods for handling touch
events, if only as stub (empty) implementations. Availability
Available in iOS 2.0 and later.
You should still be getting touchesMoved in your viewController even you are outside of your view's frame. I would add array to your custom UIView which would keep touch objects that this view is assigned to and implement the following logic:
When you receive touchesBegan - add touch object to array for given UIView where touch coordinates match (you may have to iterate over all your subviews and match coordinates with frame to find the right one)
When you receive touchesMoved - remove touch from UIView's array for previous location and add it to UIView for current location if any
When you receive touchesEnded & touchesCancelled - remove touches from all UIViews arrays
When you remove or add touch object from your custom UIView array you may call your delegate methods (implement observer pattern) because at that point you know if it's really pressed or unpressed event. Keep in mind you may have many touch objects in one array so before calling your delegate check whether you added first object or deleted last one because that's the only case you should call your delegate.
I have implemented such solution in my last game, but instead of UIViews I had virtual buttons.