我想以某种方式组织我的iPhone游戏的级别视图,但我根本不能(没有扩展Object Allocations )。我为我的代码制作了一个非常“骨架”(这个游戏有2个级别,目标是发布iPhone显示)。我只是无法释放前一级别,因此Instrunments显示增加BGTangramLevel实例。
请看一下,我需要一些有用的设计想法(我的第三个问题)。
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
BGTangramLevel.h
@interface BGTangramLevel : UIView
{
BOOL puzzleCompleted;
}
//Initializer.
+(BGTangramLevel*)levelWithColor: (UIColor*) color frame: (CGRect) frame;
//Test if the puzzle is completed.
-(void) isSolved;
@end
BGTangramLevel.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,尝试以(非原子,assign)方式合成的currentLevel属性,但是Object Allocations仍然增长。我可以避免通知吗?我被卡住了。
答案 0 :(得分:3)
您需要更密切地遵循保留/发布规则。你绝对不应该在实验中添加保留,释放和自动释放,只是为了找到有用的东西。已经有很多关于Cocoa内存管理的文章,我在此不再重复。
具体来说,BGTangramLevel的levelWithColor:frame:
方法应该在将allocatedLevel返回给调用者之前调用[allocatedLevel autorelease]
。它不拥有该对象,由调用者保留它。
您还需要了解访问实例变量和访问属性之间的区别。 Cocoa的属性只是getter和setter方法的语法糖。在视图控制器中引用currentLevel
时,您将直接处理实例变量。当您引用self.currentLevel
时,您正在处理该财产。
即使您已声明属性,currentLevel = [BGTangram ...]
也只是将引用复制到变量中。在viewDidLoad
中,如果要查看属性的setter方法,则需要使用self.currentLevel = [BGTangram ...]
,该方法将保留对象(因为您以此方式声明了属性)。看到区别?
我认为您的泄密发生在finishedCurrentLevel
。如果您使用过self.currentLevel = [BGTangram ...]
,则会调用属性的setter方法,该方法将释放旧对象并保留新对象。因为您直接分配给实例变量,所以只需覆盖旧级别的引用而不释放它。
在视图控制器的[currentLevel release]
方法中调用dealloc
是正确的。