I'm trying to call these Methods on some event:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
But i don't know how to fill the parameters :
1 - (NSSet *)touches
2 - withEvent:(UIEvent *)event
Can any one provide me with a sample parameters do call to (void)touchesEnded and (void)touchesMoved: (and
- (void)touchesBegan
There's no public constructors for UITouch and UIEvent, so you cannot generate the parameters required by the touch method.
As dasblinkenlight said, there could be surely another approach to your problem. But, the current approach is absolutely not possible.
Those methods are called automatically by the system. You never call them directly.
What you should do, well that depends on your goal. If you just want to "simulate" touches, just have helper methods. Then, have touchesXXXX call those directly.
We do not get an API to create UITouch objects, so you have to mirror them if you want to keep their information around. Something like...
#interface MyTouch : NSObject {
UITouchPhase phase
NSUInteger tapCount
NSTimeInterval timestamp
UIView *view
UIWindow *window
CGPoint locationInView;
CGPoint locationInWindow;
#end
Then, you could have a method like this...
- (void)handleTouches:(NSSet*)touches {
}
Where touches was a set of MyTouch objects.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// For UITouch in touches, create a MyTouch, and add it to your own
// collection of touches.
[self handleTouches:myTouches];
}
If you did this for each touchesXXXX method, each one of them pass off handling to your own method.
Now, by doing this, you have control over creating your own touch objects. You can make them be configured for any view, or pattern you want. Then, in any other piece of code, you can create a collection of MyTouch objects, and call handleTouches: with them.
As long as the touchesXXXX methods just create your special objects, and pass them on to your method, you can have the exact same behavior whether the system generates the touches, or you simulate them.
Now, what you DO NOT get is automatic generation of system events.
If you are getting killed by the performance of that, there are simple ways to avoid the creation of the extra set and objects, but that's not your question.
Related
I'm currently in development of a card game of sorts, and when a user plays a card, I want that card to move from its current location in the players hand to the "face up" pile on the screen.
Edit: To answer some questions, and make the question/answers clean, here is some of my code.
+(id)card:(NSString*)suit :(int) value {
HHCard *card = [HHCard new];
card.value = value;
card.suit = suit;
//used for selection of cards during human turn
card.isSelected = false;
return card;
}
Your card has to be associated with an UIView of some kind. Why not use:
[UIView animateWithDuration:animations:]
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/clm/UIView/animateWithDuration:animations:
Then in your animations block you just change the x and y coordinates to where you want the card to go. It will animate it for you.
I apologize for not answering the question sooner, however the answer is quite simple. In order to move an object, in this example a 'card' to the desired location on the screen, create a CGPoint that contains the point where you wish your object to move, and then have your object run the SKAction moveTo:(CGPoint)duration:(NSTimeInterval).
CGPoint newPosition = {newX,newY};
[yourObject runAction:[SKAction moveTo:newPosition duration:lengthOfAnimation]];
Their are 4 methods that has been provided to us, through which we can track the touch made to a view. the methods are below :
(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
You just need to apply these methods in your controller class and then can track the location of your view in these method accordingly.
Hope this may help.
I have a UITableView that has certain cells that are a different height. I was hoping to have a way, without adding a button to each cell, to not receive responses to didSelectedRowAtIndexPath, if the touches in the cell are below a certain point.
As an example, say I have two cells, one that has a height of 100 and another with a height of 150. Is there a way to not receive responses to didSelectRowAtIndexPath: for touches below 100, but still receive the touch input on the cell?
I thought of overriding the touches methods in the cell and returning the point of contact in a delegate to the controller/table and using that input to determine whether or not I will ignore the didSelectRowAtIndexPath: response, but I'm worried about the highlighting and other calls and whether it may not be fast enough to block those as well. It just seems really iffy to me.
I think without subclassing the cell, it isn't possible.
My suggestion would be to do this:
Create a Subclass of the cells
Add an extra boolean iVar to the cells, like didTapOutside
Set the boolean to True or False, based ont he Y position tap in the touchesBegan method
In the didSelectRowAtIndexPath read the didTapOutside boolean variable and according to it's setting do your actions
Example follows:
#interface MyCustomCell : UITableViewCell {
BOOL didTapOutside;
}
#property (atomic, readwrite) BOOL didTapOutside;
And the implementation:
#implementation MyCustomCell
#synthesize didTapOutside;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:touch.view];
didTapOutside = (location.y>100);
[super touchesBegan:touches withEvent:event];
}
You can create a custom UITableViewCell for example:
CustomCell *cell = [[CustomCell alloc] initWithFrame:rect reuseIdentifier:identifier];
You could override the touchesBegan method in the CustomCell and do something like the following to get the position of the touch:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGPoint point = [aTouch locationInView:self];
// point.x and point.y have the coordinates of the touch
// based on where the touch is... your custom code
[super touchesBegan:touches withEvent:event];
}
Sorry i read the question wrong at first. There is no easy solution for this.
If you do not want to use a sub class, the only thing you can do is add a transparent view or button on the area you want to detect touch and create an event on that instead of using the table view cell methods.
I have two view controllers appearing on the screen at the same time using view controller containment, implemented the same as in Apple's code example. Call them view controller A (vcA) and view controller B (vcB), and the container view controller (containerVC).
Each vcA and vcB both have a grid of objects, and I want to be able to drag objects from vcA to vcB. More specifically, I want the touch that originates in vcA to hit the touchesMoved:withEvent method in vcB once it is within the bounds vcB.
I have overridden the touchesMoved:withEvent method on the containerVC, track the touch via a hit test, and tried forwarding the touch down the UIView hierarchy like so:
// in the containerVC
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint locationPoint = [[touches anyObject] locationInView:self.view];
UIView* touchIsInViewControllerA = [vcA hitTest:locationPoint withEvent:event];
if (touchIsInViewControllerA) {
NSLog(#"Touch is in vcA");
return;
}
UIView* touchIsInViewControllerB = [vcB hitTest:locationPoint withEvent:event];
if (touchIsInViewControllerB) {
NSLog(#"Touch is in vcB");
[vcB touchesMoved:touches withEvent:event]; // this causes a crash
}
}
This seems to be recursive, with containerVC pushing the touch event down the hierarchy, then vcB passing the touch event back up the hierarchy.
My question: Is there a way to keep vcB from passing the touch event back up the responder chain to containerVC? Or should I approach this a different way - make vcB a delegate of vcA and leave containerVC out of the equation?
Note: I'm guessing a common response will be to give up the VC containment pattern and keep it all in one view controller, but for reasons not shown in this example I think keeping them separate will work better for me - unless it's utter insanity and super hacky to do so...
This problem can be solved easily by setting individual gesture object for each view controller.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (touchIsInViewControllerA) {
// calls a delegate of view controller A
}
else
{
// calls a delegate of view controller B
}
}
-(void)touchesBegan :(NSSet *)touches withEvent:(UIEvent *)event
{
[textValue resignFirstResponder];
[super touchesBegan:touches withEvent:event];
}
can someone explain me the meaning of this method???
[textValue resignFirstResponder];
Usually used to hide the keyboard if textValue control has focus at the moment.
[super touchesBegan:touches withEvent:event];
Calls the same method of parent class to preserve standard touch handling.
From the documentation;
Tells the receiver when one or more
fingers touch down in a view or
window.
The primary event-handling methods for
touches are touchesBegan:withEvent:,
touchesMoved:withEvent:,
touchesEnded:withEvent:, and
touchesCancelled:withEvent:. The
parameters of these methods associate
touches with their events, especially
touches that are new or have
changed and thus allow responder
objects to track and handle the
touches as the delivered events
progress through the phases of a
multi-touch sequence.
So, I'm capturing multiple touches and determining the number and where each of the touches occurred and I'm seeing different behavior between a UIView UIViewController.
Basically, the event handler is coded below: (in this case the touchesEnded, but it really doesn't matter). What happens in the View, is that I get the entire collection of touches, but in the controller, I get only one touch at a time, that is there is never a collection of touches, but the TouchesEnded gets executed for each touch that occurred in the same moment.
I add the subviews as identically as possible...
Can someone 'spain to me what's going on? Why doesn't the controller version give me the collection?
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
int total = 0;
for (UITouch *touch in touches)
{
for(UIView *myView in [contentView subviews])
{
if (CGRectContainsPoint([myView frame], [touch locationInView:self.view]))
total++; // this is always 1 for the UIViewController
// but I get the full number within the UIView version
}
}
}
I suspect you are getting the touches but that the views are different. Check that contentView is the same and has the same subviews.
I am not sure that I am right but this thing always work for me.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
If(touch.view==your view)
{
NSLog("do your task here");
}
}