私は最初のゲームをリリースする最終段階にあり、Instruments:Leaks&Allocationsを実行した後、保持サイクルが原因でコードにリークがあることがわかりました。私はCocos2d2.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を作成します。CCActionのシーケンスは引数によって異なりますが、通常は次のようになります。
[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以降をターゲットにしているため、利用できないと思います。
これとまったく同じように、コードに別の保持サイクルがありました。これも、CCCallFunc / CCCallBlockを含むCCSequenceを(もちろんARCで自動的に)保持することによって発生しました。必要なときにいつでも再作成することで解決しました。この場合も可能ですが、これらのアニメーションはゲーム全体で数百回トリガーされる可能性があるため、推奨されるCocos2dのベストプラクティスに従うことを望んでいました。アクションを保持します。
ありがとう!