1

どうにかして iPhone ゲームのレベルビューを整理したいのですが、( Object Allocations を展開しないと) できません。私は自分のコードの真の「スケルトン」を作成しました (このゲームには 2 つのレベルがあり、目標は iPhone ディスプレイをリリースすることです)。以前のレベルの割り当てを解除できないため、Instruments は BGTangramLevel インスタンスの増加を示しています。

それを見てください。設計に関するいくつかの役立つアイデアが必要です (それに関する私の 3 番目の質問)。

viewcontroller.h

@interface compactTangramViewController : UIViewController
{
    //The level.
    BGTangramLevel *currentLevel;
    UIColor *levelColor;
}

//It is to be just a reference, therefore I use assign here.
@property (nonatomic, retain) BGTangramLevel *currentLevel;

-(void) notificationHandler: (NSNotification*) notification;
-(void) finishedCurrentLevel;

@end

viewcontroller.m

@implementation compactTangramViewController
@synthesize currentLevel;

//Initializer functions, setting up view hierarchy.
-(void) viewDidLoad
{   

    //Set up levelstepper.
    levelColor = [UIColor greenColor];

    //Set up "state" classes.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationHandler:) name:@"finishedCurrentLevel" object:nil];   

    //Attach level 1.
    currentLevel = [BGTangramLevel levelWithColor: levelColor frame:self.view.frame];
    [self.view addSubview:currentLevel];

    [super viewDidLoad];

}

//Release objects.
-(void) dealloc
{
    [currentLevel release];
    [super dealloc];
}

//Notification handling.
-(void) notificationHandler: (NSNotification*) notification
{
    //Execute level swap.
    if ([notification name] == @"finishedCurrentLevel") [self finishedCurrentLevel];
}

-(void) finishedCurrentLevel
{
    //Remove previous level.
    [currentLevel removeFromSuperview];
    //[currentLevel release];

    //Step level.
    if (levelColor == [UIColor greenColor]) levelColor = [UIColor blueColor]; else levelColor = [UIColor greenColor];

    //Attach level 2.
    currentLevel = [BGTangramLevel levelWithColor: levelColor frame:self.view.frame];
    [self.view addSubview:currentLevel];

}
@end

BGタングラムレベル.h

@interface BGTangramLevel : UIView
{
    BOOL puzzleCompleted;   
}

//Initializer.
+(BGTangramLevel*)levelWithColor: (UIColor*) color frame: (CGRect) frame;

//Test if the puzzle is completed.
-(void) isSolved;

@end

BGタングラムレベル.m

@implementation BGTangramLevel

//Allocated instance.
+(BGTangramLevel*)levelWithColor: (UIColor*) color frame: (CGRect) frame
{
    BGTangramLevel *allocatedLevel = [[BGTangramLevel alloc] initWithFrame:frame];
    allocatedLevel.backgroundColor = color;
    return allocatedLevel;
}

//Finger released.
-(void) touchesEnded: (NSSet*)touches withEvent: (UIEvent*)event
{
    //The completement condition is a simple released tap for now...
    puzzleCompleted = YES;
    [self isSolved];    
}

//Test if the puzzle is completed.
-(void) isSolved
{
    //"Notify" viewController if puzzle has solved.
    if (puzzleCompleted) [[NSNotificationCenter defaultCenter] postNotificationName:@"finishedCurrentLevel" object:nil]; 
}

-(void) dealloc
{
    NSLog(@"Will ever level dealloc invoked."); //It is not.
    [super dealloc];
}

@end

それで、私は何をすべきですか?返されるレベル インスタンスを自動解放するようにマークし、removeFromSuperview の後に currentLevel を解放し、currentLevel プロパティを (非アトミック、割り当て) 方法で合成しようとしましたが、オブジェクト割り当てはまだ大きくなります。通知を避けることはできますか? 私は立ち往生しています。

4

1 に答える 1

3

保持/解放の規則をより厳密に従う必要があります。機能するものを見つけるためだけに、retain と release と autorelease を実験的に追加するべきではありません。Cocoa のメモリ管理についてはすでに多くのことが書かれていますが、ここでは繰り返しません。

特に、BGTangramLevel のlevelWithColor:frame:メソッドは、 [allocatedLevel autorelease]allocatedLevel を呼び出し元に返す前に呼び出す必要があります。オブジェクトを所有するのではなく、それを保持するのは呼び出し元次第です。

また、インスタンス変数へのアクセスとプロパティへのアクセスの違いも知っておく必要があります。Cocoa のプロパティは、getter および setter メソッドの単なる構文糖衣です。ビューコントローラーで参照currentLevelすると、インスタンス変数を直接扱っています。参照するときself.currentLevelは、プロパティを扱っています。

プロパティを宣言したとしてもcurrentLevel = [BGTangram ...]、参照を変数にコピーするだけです。では、オブジェクトを保持するプロパティの setter メソッドを使用する場合viewDidLoadに使用する必要がありself.currentLevel = [BGTangram ...]ます (プロパティをそのように宣言したため)。違いを見ます?

あなたのリークはで起こっていると思いますfinishedCurrentLevel。を使用していた場合はself.currentLevel = [BGTangram ...]、プロパティのセッター メソッドが呼び出され、古いオブジェクトが解放され、新しいオブジェクトが保持されます。インスタンス変数に直接割り当てるため、古いレベルへの参照を解放せずに上書きするだけです。

[currentLevel release]ビュー コントローラのメソッドの呼び出しdeallocは正しいです。

于 2009-12-02T01:10:40.780 に答える