Hi I'm new to Iphone Development.
I am creating a rotating image animation with variable speed.
How ever I got variable speed but now i want to decrease speed with touch hold on UIView.
I dont have any idea. So, can anybody help me? Can I get some code snippet for idea?
I have added some code snippet below
CABasicAnimation* rotationAnimation;
rotationAnimation =
[CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.fromValue = [NSNumber numberWithFloat: M_PI *2.0 * appDelegate.direction];
rotationAnimation.repeatCount = 1;
rotationAnimation.duration = interval;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.removedOnCompletion = YES;
[imgv.layer addAnimation:rotationAnimation forKey:#"rotation"];
if(count<=repeatcount)
{
[self performSelector:#selector(funTime) withObject:nil afterDelay:interval];
isNotRotating = TRUE;
interval = interval + addTime;
addTime = addTime+0.001;
lblCount.text = [NSString stringWithFormat:#"%d",count];
count++;
NSLog(#"duration to rotate a single rotation %f",(interval+((repeat-1) *0.10)/repeat));
}
else
{
tap=0;
isNotRotating= TRUE;
[imgv.layer removeAllAnimations];
}
Thanks in advance
i think you have trouble about detecting long time touch on UIView?
try to customize these method of your own UIView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- (void) touchesEnded...
...etc
Related
#property (SK_NONATOMIC_IOSONLY, getter = isPaused) BOOL paused;
I found this line of code that I could add into my project, how would I pause my whole game?
For example:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for (UITouch *touch in touches)
{
SKSpriteNode *pause = (SKSpriteNode*)[self childNodeWithName:#"pause"];
CGPoint location = [touch locationInNode:self];
// NSLog(#"** TOUCH LOCATION ** \nx: %f / y: %f", location.x, location.y);
if([pause containsPoint:location])
{
NSLog(#"PAUSE GAME HERE SOMEHOW");
}
}
}
As you can see, I have the button set up. When i select it, how would I pause the whole scene? And then resume it when someone hits a resume button.
OK SO I got some advice to call
self.scene.view.paused = YES;
except here is the problem, in my app delegate
- (void)applicationWillResignActive:(UIApplication *)application{
SKView *view = (SKView *)self.window.rootViewController.view;
view.paused = YES;}
and
- (void)applicationDidBecomeActive:(UIApplication *)application{
SKView *view = (SKView *)self.window.rootViewController.view;
view.paused = NO;
I make it a type SKView, when it is actually an SKScene. Anyway to fix this? Do you suggest that I make all my scenes into views by retyping all the code?
Use SKView's isPaused property:
Swift:
scene.view?.isPaused = true
Objective C:
self.scene.view.isPaused = YES;
This will stop all actions and physics simulation.
Use Scene to Paused Functionality
self.scene?.view?.paused = true
Property 'paused' has been renamed to 'isPaused'
scene?.view?.isPaused = true
When researching "How do I detect a touch event on a moving UIImageView?" I've come across several answers and I tried to implement them to my app. Nothing I've come across seems to work. I'll explain what I'm trying to do then post my code. Any thoughts, suggestions, comments or answers are appreciated!
My app has several cards floating across the screen from left to right. These cards are various colors and the object of the game is the drag the cards down to their similarly colored corresponding container. If the user doesn't touch and drag the cards fast enough, the cards will simply drift off the screen and points will be lost. The more cards contained in the correct containers, the better the score.
I've written code using core animation to have my cards float from the left to right. This works. However when attempting to touch a card and drag it toward it's container, it isn't correctly detecting that I'm touching the UIImageView of the card.
To test if my I'm properly implementing the code to move a card, I've also written some code allows movement for a non-moving card. In this case my touch is being detected and acting accordingly.
Why can I only interact with stationary cards? After researching this quite a bit it seems that the code:
options:UIViewAnimationOptionAllowUserInteraction
is the key ingredient to get my moving UIImages to be detected. However I tried this doesn't seem to have any effect.
I another key thing that I may be doing wrong is not properly utilizing the correct presentation layer. I've added code like this to my project and I also only works on non-moving objects:
UITouch *t = [touches anyObject];
UIView *myTouchedView = [t view];
CGPoint thePoint = [t locationInView:self.view];
if([_card.layer.presentationLayer hitTest:thePoint])
{
NSLog(#"You touched a Card!");
}
else{
NSLog(#"backgound touched");
}
After trying these types of things I'm getting stuck. Here is my code to understand this a bit more completely:
#import "RBViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface RBViewController ()
#property (nonatomic, strong) UIImageView *card;
#end
#implementation RBViewController
- (void)viewDidLoad
{
srand(time (NULL)); // will be used for random colors, drift speeds, and locations of cards
[super viewDidLoad];
[self setOutFirstCardSet]; // this sends out 4 floating cards across the screen
// the following creates a non-moving image that I can move.
_card = [[UIImageView alloc] initWithFrame:CGRectMake(400,400,100,100)];
_card.image = [UIImage imageNamed:#"goodguyPINK.png"];
_card.userInteractionEnabled = YES;
[self.view addSubview:_card];
}
the following method sends out cards from a random location on the left side of the screen and uses core animation to drift the card across the screen. Notice the color of the card and the speed of the drift will be randomly generated as well.
-(void) setOutFirstCardSet
{
for(int i=1; i < 5; i++) // sends out 4 shapes
{
CGRect cardFramei;
int startingLocation = rand() % 325;
CGRect cardOrigini = CGRectMake(-100,startingLocation + 37, 92, 87);
cardFramei.size = CGSizeMake(92, 87);
CGPoint origini;
origini.y = startingLocation + 37;
origini.x = 1200;
cardFramei.origin = origini;
_card.userInteractionEnabled = YES;
_card = [[UIImageView alloc] initWithFrame:cardOrigini];
int randomColor = rand() % 7;
if(randomColor == 0)
{
_card.image = [UIImage imageNamed:#"goodguy.png"];
}
else if (randomColor == 1)
{
_card.image = [UIImage imageNamed:#"goodguyPINK.png"];
}
else if (randomColor == 2)
{
_card.image = [UIImage imageNamed:#"goodGuyPURPLE.png"];
}
else if (randomColor == 3)
{
_card.image = [UIImage imageNamed:#"goodGuyORANGE.png"];
}
else if (randomColor == 4)
{
_card.image = [UIImage imageNamed:#"goodGuyLightPINK.png"];
}
else if (randomColor == 5)
{
_card.image = [UIImage imageNamed:#"goodGuyBLUE.png"];
}
else if (randomColor == 6)
{
_card.image = [UIImage imageNamed:#"goodGuyGREEN.png"];
}
_card.userInteractionEnabled = YES; // this is also written in my viewDidLoad method
[[_card.layer presentationLayer] hitTest:origini]; // not really sure what this does
[self.view addSubview:_card];
int randomSpeed = rand() % 20;
int randomDelay = rand() % 2;
[UIView animateWithDuration:randomSpeed + 10
delay: randomDelay + 4
options:UIViewAnimationOptionAllowUserInteraction // here is the method that I thought would allow me to interact with the moving cards. Not sure why I can't
animations: ^{
_card.frame = cardFramei;
}
completion:NULL];
}
}
notice the following method is where I put CALayer and hit test information. I'm not sure if I'm doing this correctly.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *t = [touches anyObject];
UIView *myTouchedView = [t view];
CGPoint thePoint = [t locationInView:self.view];
thePoint = [self.view.layer convertPoint:thePoint toLayer:self.view.layer.superlayer];
CALayer *theLayer = [self.view.layer hitTest:thePoint];
if([_card.layer.presentationLayer hitTest:thePoint])
{
NSLog(#"You touched a Shape!"); // This only logs when I touch a non-moving shape
}
else{
NSLog(#"backgound touched"); // this logs when I touch the background or an moving shape.
}
if(myTouchedView == _card)
{
NSLog(#"Touched a card");
_boolHasCard = YES;
}
else
{
NSLog(#"Didn't touch a card");
_boolHasCard = NO;
}
}
I want the following method to work on moving shapes. It only works on non-moving shapes. Many answers say to have the touch ask which class the card is from. As of now all my cards on of the same class (the viewController class). When trying to have the cards be their own class, I was having trouble having that view appear on my main background controller. Must I have various cards be from different classes for this to work, or can I have it work without needing to do so?
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if([touch view]==self.card)
{
CGPoint location = [touch locationInView:self.view];
self.card.center=location;
}
}
This next method resets the movement of a card if the user starts moving it and then lifts up on it.
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(_boolHasCard == YES)
{
[UIView animateWithDuration:3
delay: 0
options:UIViewAnimationOptionAllowUserInteraction
animations: ^{
CGRect newCardOrigin = CGRectMake(1200,_card.center.y - 92/2, 92, 87);
_card.frame = newCardOrigin;
}
completion:NULL];
}
}
#end
The short answer is, you can't.
Core Animation does not actually move the objects along the animation path. They move the presentation layer of the object's layer.
The moment the animation begins, the system thinks the object is at it's destination.
There is no way around this if you want to use Core Animation.
You have a couple of choices.
You can set up a CADisplayLink on your view controller and roll your own animation, where you move the center of your views by a small amount on each call to the display link. This might lead to poor performance and jerky animation if you're animating a lot of objects however.
You can add a gesture recognizer to the parent view that contains all your animations, and then use layer hit testing on the paren't view's presentation view to figure out which animating layer got tapped, then fetch that layer's delegate, which will be the view you are animating. I have a project on github that shows how to do this second technique. It only detects taps on a single moving view, but it will show you the basics: Core Animation demo project on github.
(up-votes always appreciated if you find this post helpful)
It looks to me that your problem is really with just an incomplete understanding of how to convert a point between coordinate spaces. This code works exactly as expected:
- (void)viewDidLoad
{
[super viewDidLoad];
CGPoint endPoint = CGPointMake([[self view] bounds].size.width,
[[self view] bounds].size.height);
CABasicAnimation *animation = [CABasicAnimation
animationWithKeyPath:#"position"];
animation.fromValue = [NSValue valueWithCGPoint:[[_imageView layer] position]];
animation.toValue = [NSValue valueWithCGPoint:endPoint];
animation.duration = 30.0f;
[[_imageView layer] addAnimation:animation forKey:#"position"];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *t = [touches anyObject];
CGPoint thePoint = [t locationInView:self.view];
thePoint = [[_imageView layer] convertPoint:thePoint
toLayer:[[self view] layer]];
if([[_imageView layer].presentationLayer hitTest:thePoint])
{
NSLog(#"You touched a Shape!");
}
else{
NSLog(#"backgound touched");
}
}
Notice the line in particular:
thePoint = [[_imageView layer] convertPoint:thePoint
toLayer:[[self view] layer]];
When I tap on the layer image view while it's animating, I get "You touched a Shape!" in the console window and I get "background touched" when I tap around it. That's what you're wanting right?
Here's a sample project on Github
UPDATE
To help with your follow up question in the comments, I've written the touchesBegan code a little differently. Imagine that you've add all of your image views to an array (cleverly named imageViews) when you create them. You would alter your code to look something like this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *t = [touches anyObject];
CGPoint thePoint = [t locationInView:self.view];
for (UIImageView *imageView in [self imageViews]) {
thePoint = [[imageView layer] convertPoint:thePoint
toLayer:[[self view] layer]];
if([[imageView layer].presentationLayer hitTest:thePoint]) {
NSLog(#"Found it!!");
break; // No need to keep iterating, we've found it
} else{
NSLog(#"Not this one!");
}
}
}
I'm not sure how expensive this is, so you may have to profile it, but it should do what you're expecting.
I'm trying to set up a CAEmitterLayer to make a confetti effect, and I've run into two issues:
Whenever I set the birthRate on my cells to something non-zero to start the animation I get a flurry of cells placed randomly on screen, which animate normally, and then the emitter continues to emit properly after that.
Whenever the emitterCells are drawing things on screen, any time I touch the screen, the emitter draws emitterCells in (seemingly) random locations that exist for a (seemingly) random amount of time. Nothing in the emitter is tied to any touch events (i.e. I'm not intentionally drawing anything on a touch event), but the layer is in a view that has multiple embedded views. The more I touch, the more cells show up.
Here's my code for setting up the emitter, and then starting and stopping it (once I've called the stop function, then taps on the screen cease creating new random elements):
- (void)setupConfetti
{
self.confettiLayer = [CAEmitterLayer layer];
[self.view.layer addSublayer:self.confettiLayer];
[self.view.layer setNeedsDisplay];
self.confettiLayer.emitterPosition = CGPointMake(1024.0/2,-50.0);
self.confettiLayer.emitterSize = CGSizeMake(1000.0, 10.0);
self.confettiLayer.emitterShape = kCAEmitterLayerLine;
self.confettiLayer.renderMode =kCAEmitterLayerUnordered;
CAEmitterCell *confetti = [CAEmitterCell emitterCell];
confetti1.contents = (id)[[UIImage imageNamed:#"confetti.png"] CGImage];
confetti.emissionLongitude = M_PI;
confetti.emissionLatitude = 0;
confetti.lifetime = 5;
confetti.birthRate = 0.0;
confetti.velocity = 125;
confetti.velocityRange = 50;
confetti.yAcceleration = 50;
confetti.spin = 0.0;
confetti.spinRange = 10;
confetti.name = #"confetti1";
self.confettiLayer.emitterCells = [NSArray arrayWithObjects:confetti, nil];
}
To start the confetti:
- (void)startConfettiAnimation
{
[self.confettiLayer setValue:[NSNumber numberWithInt:10.0] forKeyPath:#"emitterCells.confetti.birthRate"];
}
And to stop it:
- (void)stopConfettiAnimation
{
[self.confettiLayer setValue:[NSNumber numberWithInt:0.0] forKeyPath:#"emitterCells.confetti.birthRate"];
}
Again, once it gets started, after the initial flurry of random elements, this works just fine: everything animates normally, and when the birthRate is later set to zero, it ends gracefully. It just seems to respond to touch events, and I have no idea why. I've tried adding the emitterLayer to a different view, disabling user interaction on that view, and then adding it as a subview of the main view, and that didn't seem to work.
Any help/insight would be much appreciated!
Thanks,
Sam
I know this is an old post, but I also had this problem.
Jackslash answers it well in this post:
iOS 7 CAEmitterLayer spawning particles inappropriately
You need to set beginTime on your emitter layer to begin at the current time with CACurrentMediaTime(). It seems the problem we have occurs because the emitter started already in the past.
emitter.beginTime = CACurrentMediaTime();
Could it be that you aren't checking to see if the particle is emitting like in the Wenderlich example Artur Ozieranski posted? I'm not seeing the doubling as long as the check is in place.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[fireView setEmitterPositionFromTouch: [touches anyObject]];
[fireView setIsEmitting:YES];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[fireView setIsEmitting:NO];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[fireView setIsEmitting:NO];
}
-(void)setIsEmitting:(BOOL)isEmitting
{
//turn on/off the emitting of particles
[fireEmitter setValue:[NSNumber numberWithInt:isEmitting?200:0] forKeyPath:#"emitterCells.fire.birthRate"];
}
.h file
#import <UIKit/UIKit.h>
#interface DWFParticleView : UIView
-(void)setEmitterPositionFromTouch: (CGPoint*)t;
-(void)setIsEmitting:(BOOL)isEmitting;
#end
.m file
#import "DWFParticleView.h"
#import <QuartzCore/QuartzCore.h>
#implementation DWFParticleView
{
CAEmitterLayer* fireEmitter; //1
}
-(void)awakeFromNib
{
//set ref to the layer
fireEmitter = (CAEmitterLayer*)self.layer; //2
//configure the emitter layer
fireEmitter.emitterPosition = CGPointMake(50, 50);
fireEmitter.emitterSize = CGSizeMake(10, 10);
CAEmitterCell* fire = [CAEmitterCell emitterCell];
fire.birthRate = 0;
fire.lifetime = 1.5;
fire.lifetimeRange = 0.3;
fire.color = [[UIColor colorWithRed:255 green:255 blue:255 alpha:0.1] CGColor];
fire.contents = (id)[[UIImage imageNamed:#"Particles_fire.png"] CGImage];
[fire setName:#"fire"];
fire.velocity =5;
fire.velocityRange = 20;
fire.emissionRange = M_PI_2;
fire.scaleSpeed = 0.1;
fire.spin = 0.5;
fireEmitter.renderMode = kCAEmitterLayerAdditive;
//add the cell to the layer and we're done
fireEmitter.emitterCells = [NSArray arrayWithObject:fire];
}
+ (Class) layerClass //3
{
//configure the UIView to have emitter layer
return [CAEmitterLayer class];
}
-(void)setEmitterPositionFromTouch: (CGPoint*)t
{
//change the emitter's position
fireEmitter.emitterPosition = (*t);
}
-(void)setIsEmitting:(BOOL)isEmitting
{
//turn on/off the emitting of particles
[fireEmitter setValue:[NSNumber numberWithInt:isEmitting?100:0] forKeyPath:#"emitterCells.fire.birthRate"];
}
#end
I used this code for create a custom view and to emit particles on
touch
Here is the call statement for emission of particle on touch
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInView:self.view];
[fireView setEmitterPositionFromTouch: &p];
[fireView setIsEmitting:YES];
}
may be it will work for you .
I'm designing an app that involves linear graphs. What I have right now is a line with three dots: one in the center for moving the whole line, and the other two, lower and higher on the line, for rotating it. The problem that I have is figuring out how to rotate the other two dots when the user touches on either of them.
I haven't actually done much with the rotation dots yet, but here's my code so far:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* touch = [touches anyObject];
CGPoint point = [touch locationInView:graph];
if (CGRectContainsPoint(moveDot.frame, point)) {
moveDotIsTouched = YES;
}
if (CGRectContainsPoint(rotateDot1.frame, point)) {
rotateDot1IsTouched = YES;
}
if (CGRectContainsPoint(rotateDot2.frame, point)) {
rotateDot2IsTouched = YES;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* touch = [touches anyObject];
CGPoint point = [touch locationInView:graph];
if (moveDotIsTouched) {
if ((point.y > 0) && (point.y < 704))
{
if (point.y < 64) {rotateDot1.hidden = YES;}
else {rotateDot1.hidden = NO;}
if (point.y > 640) {rotateDot2.hidden = YES;}
else {rotateDot2.hidden = NO;}
moveDot.center = CGPointMake(moveDot.center.x, point.y);
rotateDot1.center = CGPointMake(moveDot.center.x+64, moveDot.center.y-64);
rotateDot2.center = CGPointMake(moveDot.center.x-64, moveDot.center.y+64);
graph.base = -(point.y)/32 + 11;
if (graph.base < 0) {[functionField setText:[NSString stringWithFormat:#"y = %.2fx %.2f", graph.slope, graph.base]];}
else if (graph.base > 0) {[functionField setText:[NSString stringWithFormat:#"y = %.2fx + %.2f", graph.slope, graph.base]];}
else {[functionField setText:[NSString stringWithFormat:#"y = %.2fx", graph.slope]];}
[yintField setText:[NSString stringWithFormat:#"%.2f", graph.base]];
[self changeTable];
}
}
[graph setNeedsDisplay];
}
The numbers involving the positioning of the dots are measured in pixels. The only way I can really think of rotating the outside dots is by calculating a radius and making sure the dots are within the radius, but I'm wondering if there isn't something simpler than that. Does anyone know a simple way to move a UIImageView in a circle?
KTOneFingerRotationGestureRecognizer is a custom UIGestureRecognizer for doing one finger rotations in iOS apps. It tracks finger movement around a central point. I don't know if this is exactly what you want, but it may point you in the right direction.
I'm developing a game that will use the force of the swipe as a variable user input.
I read from the documentation that on the touchesEnded event, I can get the allTouches array which is a list of the user touches collected from touchesBegan. From this I plan to get the last two touches to get the direction of the swipe. I will also get the time interval between touchesBegan and touchesEnded, from which I will get the speed of the swipe. I will use the direction and the speed to calculate the force of the swipe.
What I'd like to know is: is there a better way to do this? Is this already encapsulated in a library call somewhere?
Thanks in advance.
Solve like this
- (void)rotateAccordingToAngle:(float)angle
{
[spinWheel setTransform:CGAffineTransformRotate(spinWheel.transform, angle)];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[spinWheel.layer removeAllAnimations];
previousTimestamp = event.timestamp;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if (touch.view==spinWheel)
{
UITouch *touch = [touches anyObject];
CGPoint center = CGPointMake(CGRectGetMidX([spinWheel bounds]), CGRectGetMidY([spinWheel bounds]));
CGPoint currentTouchPoint = [touch locationInView:spinWheel];
CGPoint previousTouchPoint = [touch previousLocationInView:spinWheel];
CGFloat angleInRadians = atan2f(currentTouchPoint.y - center.y, currentTouchPoint.x - center.x) - atan2f(previousTouchPoint.y - center.y, previousTouchPoint.x - center.x);
[self rotateAccordingToAngle:angleInRadians];
CGFloat angleInDegree = RADIANS_TO_DEGREES(angleInRadians);
revolutions+= (angleInDegree/360.0f);
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if (touch.view==spinWheel)
{
NSTimeInterval timeSincePrevious = event.timestamp - previousTimestamp;
CGFloat revolutionsPerSecond = revolutions/timeSincePrevious;
NSLog(#"%.3f",revolutionsPerSecond);
[self startAnimationWithRevolutions:revolutionsPerSecond forTime:5.0f];
}
revolutions = 0;
}
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
spinWheel.userInteractionEnabled = TRUE;
if (timerUpdate) {
[timerUpdate invalidate];
timerUpdate = nil;
}
}
-(void)updateTransform{
spinWheel.transform = [[spinWheel.layer presentationLayer] affineTransform];
}
-(void)startAnimationWithRevolutions:(float)revPerSecond forTime:(float)time
{
spinWheel.userInteractionEnabled = FALSE;
float totalRevolutions = revPerSecond * time;
timerUpdate = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:#selector(updateTransform) userInfo:nil repeats:YES];
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:time] forKey:kCATransactionAnimationDuration];
CABasicAnimation* spinAnimation = [CABasicAnimation
animationWithKeyPath:#"transform.rotation"];
CGAffineTransform transform = spinWheel.transform;
float fromAngle = atan2(transform.b, transform.a);
float toAngle = fromAngle + (totalRevolutions*4*M_PI);
spinAnimation.fromValue = [NSNumber numberWithFloat:fromAngle];
spinAnimation.toValue = [NSNumber numberWithFloat:toAngle];
spinAnimation.repeatCount = 0;
spinAnimation.removedOnCompletion = NO;
spinAnimation.delegate = self;
spinAnimation.timingFunction = [CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseOut];
[spinWheel.layer addAnimation:spinAnimation forKey:#"spinAnimation"];
[CATransaction commit];
}
I've accomplished something along these lines rather simply by just comparing [touch locationInView:self] to [touch previousLocationInView:self] in touchesEnded of the Class (subclass of UIView) of the object that will be moved. This will give you a vector with location, direction & rough sense of velocity at the moment user released finger from the iPhone.
You could use a UIPanGestureRecognizer which has function velocityInView. See https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIPanGestureRecognizer_Class/
Rather than using allTouches on the UIEvent, you should use the touches set that you get in the call to your UIView's (or other UIResponder's) touchesEnded:withEvent: method. This ensures that you don't get touches that belong to other views.
Since the iPhone is a multi-touch device, the set contains all the touches that are associated with that event. In other words, if the user is touching the screen with two fingers, there should be two UITouch objects in the set, etc.
This means that the set does not contain all the points traversed since a touch began until it ended. To track that, you have to save the start point and time in touchesBegan:withEvent:, and then when the touch ends you calculate the speed based on that.
Note that if the set contains several points (which means the user is touching the screen with several fingers), you have to try to keep track of which UITouch object corresponds to which finger. You will want to do this in touchesMoved:withEvent:.
Since you get the touches in a set, you can't use an index or some key value to keep track of the touches you are interested in. I believe that the recommended way of doing this is to just assume that the touch that is closest to the point you saved on the previous event comes from the same finger. If you want to be more exact you can also use the UITouch's previousLocationInView: method.
If you're lazy, you can also simply do [[touches allObjects] objectAtIndex:0] and hope that this will give you the right touch (ie the one originating from the same finger) on each event. This actually often works, but I don't think you should use it in production code, especially not if you're trying to create an app with multi-touch functionality.