Here's the error message I'm getting:
I have a view which accepts multiple touches. Here's the behavior I want:
- When one touch is present, its movements should tell its delegate to perform a translation.
- When two touches are present, the movements of the first one should tell the delegate to perform a translation, while movements of either should tell its delegate to perform a rotation (based on the angle between the two points.)
- Whenever two touches were present, but the first one goes away, the second one should become the new first one.
- Other touches should be ignored.
Here's my code:
I have noticed that just before the crash occurs, I will have two fingers down but it will act as if only one is down. It appears that it properly logs that both fingers are there.
Other times it'll crash if I have zero fingers present, but it'll act like I already have one down.
Code:
*** -[NSConcreteValue class]: message sent to deallocated instance 0x100cef990
I have a view which accepts multiple touches. Here's the behavior I want:
- When one touch is present, its movements should tell its delegate to perform a translation.
- When two touches are present, the movements of the first one should tell the delegate to perform a translation, while movements of either should tell its delegate to perform a rotation (based on the angle between the two points.)
- Whenever two touches were present, but the first one goes away, the second one should become the new first one.
- Other touches should be ignored.
Here's my code:
Code:
- (void)touchesBeganWithEvent:(NSEvent*)event
{
NSMutableSet* unprocessedTouches = [[event touchesMatchingPhase:NSTouchPhaseAny inView:self] mutableCopy];
if (!touchIdentifier[0])
{
NSLog(@"First touch began.");
NSTouch* firstTouch = (NSTouch*)[unprocessedTouches anyObject];
touchIdentifier[0] = firstTouch.identity;
currentPosition = firstTouch.normalizedPosition;
[unprocessedTouches removeObject:firstTouch];
}
else
{
NSLog(@"First touch already exists.");
}
if (!touchIdentifier[1] && [unprocessedTouches count])
{
NSLog(@"Second touch began.");
NSTouch* secondTouch = (NSTouch*)[unprocessedTouches anyObject];
touchIdentifier[1] = secondTouch.identity;
otherPosition = secondTouch.normalizedPosition;
currentRotation = atan((secondTouch.normalizedPosition.y - currentPosition.y)/(secondTouch.normalizedPosition.x - currentPosition.x));
}
else
{
NSLog(@"Either there wasn't another touch, or the second touch already existed.");
}
[unprocessedTouches release];
}
- (void)touchesMovedWithEvent:(NSEvent*)event
{
NSMutableSet* unprocessedTouches = [[event touchesMatchingPhase:NSTouchPhaseAny inView:self] mutableCopy];
if (touchIdentifier[0])
{
[unprocessedTouches enumerateObjectsUsingBlock:^(NSTouch* obj, BOOL* stop)
{
if ([obj.identity isEqual: touchIdentifier[0]])
{
NSTouch* firstTouch = obj;
[delegate translation:CGPointMake((firstTouch.normalizedPosition.x - currentPosition.x), (firstTouch.normalizedPosition.y - currentPosition.y))];
currentPosition = firstTouch.normalizedPosition;
[unprocessedTouches removeObject:firstTouch];
*stop = YES;
}
}];
}
if (touchIdentifier[1] && [unprocessedTouches count])
{
[unprocessedTouches enumerateObjectsUsingBlock:^(NSTouch* obj, BOOL* stop)
{
if ([obj.identity isEqual: touchIdentifier[1]])
{
NSTouch* secondTouch = obj;
otherPosition = secondTouch.normalizedPosition;
float newRotation = atan((secondTouch.normalizedPosition.y - currentPosition.y)/(secondTouch.normalizedPosition.x - currentPosition.x));
[delegate rotation:newRotation-currentRotation];
currentRotation = newRotation;
[unprocessedTouches removeObject:secondTouch];
*stop = YES;
}
}];
}
[unprocessedTouches release];
}
- (void)touchesEndedWithEvent:(NSEvent*)event
{
NSMutableSet* unprocessedTouches = [[event touchesMatchingPhase:NSTouchPhaseEnded | NSTouchPhaseCancelled inView:self] mutableCopy];
if (touchIdentifier[1])
{
[unprocessedTouches enumerateObjectsUsingBlock:^(NSTouch* obj, BOOL* stop)
{
if ([obj.identity isEqual: touchIdentifier[1]])
{
NSLog(@"Second touch ended.");
touchIdentifier[1] = NULL;
[unprocessedTouches removeObject:obj];
*stop = YES;
}
}];
}
[unprocessedTouches enumerateObjectsUsingBlock:^(NSTouch* obj, BOOL* stop)
{
if (touchIdentifier[0] && [obj.identity isEqual: touchIdentifier[0]])
{
if (touchIdentifier[1])
{
NSLog(@"First touch ended. Second touch is new first touch.");
currentPosition = otherPosition;
touchIdentifier[0] = touchIdentifier[1];
touchIdentifier[1] = NULL;
}
else
{
NSLog(@"First touch ended.");
touchIdentifier[0] = NULL;
}
[unprocessedTouches removeObject:obj];
*stop = YES;
}
}];
[unprocessedTouches release];
}
- (void)touchesCancelledWithEvent:(NSEvent *)event
{
[self touchesEndedWithEvent:event];
}
I have noticed that just before the crash occurs, I will have two fingers down but it will act as if only one is down. It appears that it properly logs that both fingers are there.
Other times it'll crash if I have zero fingers present, but it'll act like I already have one down.
Last edited: