How to make 'touchesBegan' method work for a specific view? - iphone

In my add contact page, i have a view and a scrollview on it and again a view on it. and in that last view i ve textboxes, etc. i have given the 'touchesBegan' method but it is called only for the view at the bottom. how to point that method to another view i.e., the view at the top?
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.AddView endEditing:YES];
}

One way this is how you can do :
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch= [touches anyObject];
if ([touch view] == image1)
{
//Action
}
}
Please Note : As you are using UIScrollView you might not able to get touches method for UIScrollView. In that case you might have to use UIGesture.

Here is the answer in Swift:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
if(touch.view == myView){
// Code
}
}

First check the property UserInteractionEnabled of that whole controls and set to YES
After check out your bottom view frame that its not over on that views
And after you can checkout that with bellow condition and do something with particular controls touch event..
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
[touch locationInView:viewBoard];
if([touch.view isKindOfClass:[UIImageView class]])
{
UIImageView *tempImage=(UIImageView *) touch.view;
if (tempImage.tag == yourImageTag)
{
/// write your code here
}
}
}

try this :
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch1 = [touches anyObject];
CGPoint touchLocation = [touch1 locationInView:self.finalScore];
if(CGRectContainsPoint(YourView.frame, touchLocation));
{
//Do stuff.
}
}

try
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event touchesForView:vTouch] anyObject];
if(!touch)
return;
CGPoint pointNow = [touch locationInView:otherView];
{
// code here
}
}

If your view is a parent view then can use this code:
if let touch = touches.first {
let position = touch.location(in: yourView)
let pnt: CGPoint = CGPoint(x: position.x, y: position.y)
if (yourView.bounds.contains(pnt)) {
//You can use: yourView.frame.contains(pnt)
//OK.
}
}

Referring to the Apple documentation on UIResponder, all UIView objects (which includes UIWindow), UIApplication object, UIViewController objects are all instances of UIResponder. To handle a specific type of event, a responder must override the corresponding methods.
In our case touches is our type of event. So our responder should implement the following methods.
touchesBegan(:with:), touchesMoved(:with:), touchesEnded(:with:), and touchesCancelled(:with:)
Since we only wish to know when a user has touched a particular view, we only need to implement touchesBegan(_:with:). Since we are not overriding the other methods we must call super.touchesBegan(touches, with: event). If we were overriding ALL of the other methods, we wouldn't be required to call super.
Looking at touchesBegan(_:with:) the parameter touches is a set of UITouch instances. Each instance represents the touches for the starting phase of the event, which is represented by the parameter event.
For touches in a view, this set contains only one touch by default. Hence touches.first is the only UITouch instance in the set. We then access the property view, this represents the view or window in which the touch occurred. Lastly we compare the view that has been touched with your desired view.
It should be noted that if you wish to receive multiple touches- you must set the view's isMultipleTouchEnabled property to true. Then the set of touches will have more than one UITouch instance and you will have to handle that accordingly.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if let touch = touches.first, touch.view == myView {
// Do something
}
}

Related

Touchesbegan updating each frame

I am making a game where there is a button: while the button is pressed(touched), the player moves forward. When the button is released, the player stops moving.
Now I can do this with the touchesbegan and touchesended functions but that is not what I want since I am going to add more buttons and enable multitouch, there must be an easier way..
Anyone knows how?
How to retrieve the touch location in swift
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch = touches.anyObject()! as UITouch
let location = touch.locationInView(self)
}
You can do the same for all the other functions
Here is the answer for Objective-C, although being familiar with frames, locations on screen, layer properties etc is highly recommended as this solution detects coincidences between the user's touch and the location of the elements in the screen (I'm talking about portrait, landscape... animations, etc).
Hope it helps.
(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (CGRectContainsPoint(aViewForExample.frame, touchLocation)){
//the user has touched within this element, so what's next?
}
}

Call touchesEnded only if no touches on view

Currently, if I tap with two fingers on my screen and remove one of them but keep pressing with the other finger, the touchesEnded-method will get called.
But I want that the method only does something if there are no more touches in the view.
How can I check within the touchesEnded-method if there are still touches on the scene?
The touchesBegan and touchesEnded methods get called each time for each touch that occurs on the screen. Each touch on the screen is associated with a UITouch object. You can find all touches that are associated with the event in the (NSSet*) touches object that is a parameter for these methods.
You need to keep track of the original touch using a global variable.
In your gameScene's implementation:
#implementation GameScene
{
UITouch* currentTouch; //This variable will keep track of the touch.
}
Now, in the touchesBegan method:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
if (currentTouch == nil) {
currentTouch = touch;
//Handle touch code here, not outside.
}
}
}
And in the touchesEnded method:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
if ([touch isEqual:currentTouch]) {
//This is the tracked touch, handle touch ending here.
currentTouch = nil;
}
}
}
The above code should help you handle touch for a single touch object.
For a better understanding, you can read up on the Apple's touch handling guide here.

How can you detect if SKShapeNode is touched?

I created a sknodeshape. How can I detect if the shape I made was touched(clicked)?
Here is the code: (I solved it already)
//metung_babi is the name of the SKShapeNode
UITouch *touch = [touches anyObject];
CGPoint nokarin = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:nokarin];
if ([node.name isEqualToString:#"metung_babi"]) {
NSlog(#"touch me not");
}
my mistake was when I created the shape I put the SKShapeNode name before initializing it.
Implement the touch delegate methods. Then, in the -touchesBegan: method, extract the point of touch and retrieve the node using the [self nodeAtPoint:] method
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *yourNode = ....;
CGRect yourNodeFrame = bowlNode.frame;
if (CGRectContainsPoint(yourNodeFrame, location)) {
//your node may be touched, check if it's your node
SKNode *theNode = [self nodeAtPoint:location];
if ([theNode.name isEqualTo:yourNode.name]) {
//it's your node touched
}
}
}
the method nodeAtPoint return value is complicated. you can check the document to find different situations

To find what object is underneath our touch when touch moved

How to determine the property or perhaps the object underneath the object i am hovering or dragging?
To put my question clearly, lets take I am hovering a uiview, I want to find out what (object or view) is underneath the view I am hovering.
in custom view you can override touchesEnded method.This sample code may help your custom view hit test problem.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if ([touches count] == 1) {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:custom_view];
if (CGRectContainsPoint(custom_view.bounds, point)) {
//if touch hit to custom_view
};
}
[super touchesEnded:touches withEvent:event];
}
For one, if you know the frames of both objects you can use CGRectIntersectsRect.
if (CGRectIntersectsRect(topObjectsRect, bottomObjectsRect)) {
//
}
Additionally, you could get the point that was touched and then use the following to check if that point is in a certain rectangle.
if (CGRectContainsPoint(CGRectMake(someX, someY, someWidth, someHeight), pointOfTouch))
{
//
}

iPhone - ignoring the second touch on an area

I have a view that the users are allowed to finger paint. The code is working perfectly if the area is touched with one finger. For example: I touch it with one finger and move the finger. Then, a line is drawn as I move the first finger. If I touch with a second finger the same view, the line that was being drawn by the first finger stops.
I would like to ignore any touch beyond the first, i.e., to track the first touch but ignore all others to the same view.
I am using touchesBegan/moved/ended.
I have used this to detect the touches
UITouch *touch = [[event allTouches] anyObject];
lastPoint = [touch locationInView:myView];
I have also tried this
lastPoint = [[touches anyObject] locationInView:myView];
but nothing changed.
How do I do that - track the first touch and ignore any subsequent touch to a view?
thanks.
NOTE: the view is NOT adjusted to detect multiple touches.
A given touch will maintain the same memory address as long as it is in contact with the screen. This means you can save the address as an instance variable and ignore any events from other objects. However, do not retain the touch. If you do, a different address will be used and your code won't work.
Example:
Add currentTouch to your interface:
#interface MyView : UIView {
UITouch *currentTouch;
...
}
...
#end
Modify touchesBegan: to ignore the touch if one is already being tracked:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(currentTouch) return;
currentTouch = [touches anyObject];
...
}
Modify touchesMoved: to use currentTouch instead of getting a touch from the set:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(!currentTouch) return;
CGPoint currentPoint = [currentTouch locationInView:myView];
...
}
Modify touchesEnded: and touchesCancelled: to clear currentTouch, but only if currentTouch has ended or been cancelled.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(currentTouch && currentTouch.phase == UITouchPhaseEnded) {
...
currentTouch = nil;
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
if(currentTouch && currentTouch.phase == UITouchPhaseCancelled) {
...
currentTouch = nil;
}
}
yourView.multipleTouchEnabled = NO;
From the reference documents on UIView
multipleTouchEnabled
A Boolean value that indicates whether
the receiver handles multitouch
events.
#property(nonatomic, getter=isMultipleTouchEnabled) BOOL
multipleTouchEnabled Discussion
When set to YES, the receiver receives
all touches associated with a
multitouch sequence. When set to NO,
the receiver receives only the first
touch event in a multitouch sequence.
The default value of this property is
NO.
Other views in the same window can
still receive touch events when this
property is NO. If you want this view
to handle multitouch events
exclusively, set the values of both
this property and the exclusiveTouch
property to YES.