This is a nice catch! It could be possible that this bug existed in Sparrow before the change to ARC. I can't figure out the solution, but it seems the problem is related to the touch handling and SPTouch retaining the movieclip as the target.
Possible touch events that actually cause a dealloc:
- Slow touch down and touch up
- Touch down and move
- Touch down twice
I believe the touches remain retained until the next set of touches are processed, which also means the target of the touches will remain retained. I am really rusty with MRC, so I can't even imagine a way to implement SPTouch's target property while keeping a weak instance.
I can only think of a workaround for this scenario:
@interface SPTouch (Internal)
- (void)setTarget:(SPDisplayObject *)target;
@end
...
//Release the target for all the touches
for (SPTouch *touch in event.touches) {
[touch setTarget:nil];
}
Full code:
#import "Game.h"
@interface SPTouch (Internal)
- (void)setTarget:(SPDisplayObject *)target;
@end
@implementation Game {
SPMovieClip *_clip;
}
- (id)init
{
if ((self = [super init]))
{
_clip = [[SPMovieClip alloc]initWithFrame:[SPTexture textureWithContentsOfFile:@"Default.png"] fps:2];
[self addChild:_clip];
[_clip stop];
[[Sparrow juggler] addObject:_clip];
[_clip addEventListener:@selector(onTouch:)
atObject:self
forType:SP_EVENT_TYPE_TOUCH];
[_clip addEventListener:@selector(onComplete:)
atObject:self
forType:SP_EVENT_TYPE_COMPLETED];
}
return self;
}
- (void)onTouch:(SPTouchEvent*)event
{
[_clip play];
//Release the target for all the touches
for (SPTouch *touch in event.touches) {
[touch setTarget:nil];
}
}
- (void)onComplete:(SPEvent*)event
{
[self removeChild:_clip];
[[Sparrow juggler] removeObject:_clip];
_clip = nil;
}
@end
Of course, you wouldn't want to do this for any other scenario. Again, my MRC knowledge is very rusty, so I could be overlooking the obvious.
Hopefully someone (Daniel) can shed some light on this.