我正处于发布我的第一个游戏的最后阶段,在运行 Instruments:Leaks & Allocations 之后,我发现我的代码中有一个由保留周期引起的泄漏。我正在使用 Cocos2d 2.0,并使用 ARC 编译我的应用程序,我应该提到我在 ARC 之前启动了项目,并使用 Xcode 重构工具对其进行了转换。我的游戏每个屏幕都有几个动画对象,每个对象都有少量 (1-7) 动画“变体”该对象(即谷仓打开一次显示一匹马,另一次显示一匹斑马)。我有一个代表每个动画的类,以及每个变体的另一个类。该变体从一系列帧创建一个 CCAnimation,然后创建一个动作,该动作将在正确区域收到触摸事件时运行。此操作是导致我的保留周期的原因。
@interface AnimationVariant : NSObject
{
@private
CCAction* _action;
...
}
@property (readonly, nonatomic) CCAction* action;
...
-(void) setupActionWithMask:(int)mask
cycles:(int)cycles
hasScale:(bool)hasScale
scale:(float)scale
masterScale:(float)master_scale
animationFrames:(NSArray*) frames
duration:(float)duration
andBlock:(VoidBlock)block;
@end
在 setupActionWithMask 方法的实现中,我建立了一个 CCActions 的 NSMutableArray,actionList。CCActions 的顺序取决于 args,但通常看起来像这样:
[actionList addObject:[CCScaleTo actionWithDuration:0.0f scale:scale]];
[actionList addObject: [CCAnimate actionWithAnimation:animation] ];
[actionList addObject:[CCScaleTo actionWithDuration:0.0f scale:master_scale]];
[actionList addObject: [CCCallBlock actionWithBlock:block]];
我创建了这样的动作:
_action = [CCSequence actionMutableArray:actionList];
消费类创建一个 AnimationVariant 实例,设置它的属性,调用 setupActionWithMask,并传入一个它想要在动作完成时执行的块。当消费类想要播放动画变体时,它会这样做:
[self runAction: variant.action];
我尝试将 _action 声明为:
CCAction* __unsafe_unretained _action;
这当然打破了保留周期,但是该操作被破坏了,并且在需要时不再存在(这是您所期望的,因为 __unsafe_unretained 不保留)。我知道 __weak 是推荐的解决方案,但由于我的目标是 iOS 4 及更高版本,我认为它不适合我。
我的代码中有另一个保留周期,就像这个一样,也是由保留(当然是自动使用 ARC)包含 CCCallFunc/CCCallBlock 的 CCSequence 引起的。我通过在需要时重新创建它来解决这个问题,在这种情况下我也可以这样做,但是这些动画在整个游戏中可能会触发几百次,所以我希望遵循推荐的 Cocos2d 最佳实践并保留动作。
谢谢!