【问题标题】:Basic IOS OOP - structure and implementation基本 IOS OOP - 结构和实现
【发布时间】:2011-10-05 12:07:09
【问题描述】:

我正在为我的孩子们在 iOS 中创建一个基本的猜谜游戏,但我认为在我应该如何在应用程序的整个生命周期中创建和发布对象的理解上存在一些根本性的差距。我一直在阅读有关保留和发布周期的信息,但我认为我的问题更多与应用程序的基本架构有关,以及我在尝试实例化然后杀死应用程序的一些关键对象时可能表现不佳。

问题集中在两个特定的类上。

我有一个游戏类,我设计它来保存游戏运行所需的所有信息。当它被初始化时,它包含所有指向数组的实例变量,这些数组包含各种线索等字符串。它基本上是游戏所需所有数据的容器。

我有一个游戏视图控制器,它创建一个游戏类的实例并对其进行查询,以便在屏幕上显示游戏对象中包含的各种元素。

这很好用。当用户开始一个新游戏时,游戏类的一个新实例被分配并初始化,然后他们就离开了。

当我来生成一个新游戏时,问题就出现了。这会以多种方式发生。要么用户完成游戏并开始另一个游戏,要么用户退出当前游戏然后开始新游戏。

在我的想法中,我会释放游戏对象并分配并初始化一个新对象。但是,我注意到在设备上运行并查看分析器,游戏对象根本没有释放。它仍然存在,游戏的每个实例化都会创建一个新的游戏对象,旧的游戏对象仍然坐在那里,没有指针给它。

摆弄代码,我注意到我没有在 Game 类中实现 dealloc 方法...但是当我尝试这样做时,应用程序崩溃了,我怀疑是因为我试图释放以前发布的对象.

理想情况下,我要做的是摆脱旧的 Game 对象,或者每次开始新游戏时用新的对象替换旧的(覆盖)。

但是,这种方法是错误的吗?我应该以完全不同的方式来做吗?比如只创建一个游戏类的实例并在该类中重写一个方法以生成一组新的线索,等等每次新游戏开始并且 GameViewController 告诉它?

是否有“最佳实践”方式来做到这一点?

所以你已经知道我在做什么了,下面是 GameViewController 的代码,其中创建了 Game 类的一个实例:

#import "GameViewController.h"

@implementation GameViewController

@synthesize game =  _game;


-(void)startNewGameOfLevel:(NSInteger)level
    {
        if(!_game)
        {
            Game *g = [[Game alloc]initGamewithLevel:level]; 
            [self setGame:g];
            [g release]; g = nil;
        }

        [self set_currentlevel:[_game _currentLevel]];

        // set up popover to show the rounds goal letter
        [self setUpPopOver];

    }

-(void)quitTheCurrentGameAndStartNewGame
{
    [_game release]; _game = nil;
    [self clearGamePlayingField];
     animationStepIndex =  0;
    [self startNewGameOfLevel: _currentlevel];
}

具有指定游戏类初始化器的游戏类(删节):

    #import "Game.h"


    @implementation Game

    @synthesize arrayOfLowerCaseLetters = _arrayOfLowerCaseLetters;
    @synthesize arrayOfPhrases=  _arrayOfPhrases;

    @synthesize goalLetter = _goalLetter;
    @synthesize goalPhrase = _goalPhrase;
    @synthesize gameLetterPool = _gameLetterPool;

    @synthesize _indexForGoalLetter, _numberOfLevelsInGame, _currentLevel, _numberOfWhackHoles, _numberOfLettersInGameLetterPool;

    -(id)initGamewithLevel:(NSInteger)level
    {
        [super init];

        //create an array of lower case letters. These will
        //contain the full alphabet of all possible letters

        NSArray *arrayOfLCLetters = [[NSArray alloc] initWithObjects:@"a", @"b", @"c", @"d",@"e", @"f", @"g", @"h", @"i", @"j", @"k", @"l", @"m", @"n", @"o", @"p", @"qu", @"r", @"s", @"t", @"u", @"v", @"w", @"x",@"y", @"z",@"ch", @"sh", @"th", nil];
        [self setArrayOfLowerCaseLetters: arrayOfLCLetters];
        [arrayOfLCLetters release];arrayOfLCLetters = nil;

        //create an array of phrases.
        // These must correspond with each of the letters. e.g. a = apple.

        NSArray *phrases= [[NSArray alloc ] initWithObjects:
                           @"apple",
                           @"butterfly",
                           @"cat",
                           @"dog",
                           @"egg",
                           @"frog",
                           @"ghost",
                           @"horse",
                           @"igloo",
                           @"jam",
                           @"kite",
                           @"leaf",
                           @"moon",
                           @"nut",
                           @"orange",
                           @"pig",
                           @"queen",
                           @"rabbit",
                           @"snake",
                           @"tree",
                           @"umbrella",
                           @"van",
                           @"water",
                           @"x-ray",
                           @"yak",
                           @"Zebra",
                           @"chair",
                           @"shoes",
                           @"thumb",

                           nil];
        [self setArrayOfPhrases:phrases];
        [phrases release]; phrases = nil;


        //choose a random number to be the index reference for
        // each goal letter and goal phrase.
        [self set_indexForGoalLetter:(arc4random()%[_arrayOfLowerCaseLetters count])];
        NSLog(@"index for goal letter is:, %i", _indexForGoalLetter);

        //set Goal letter and goal phrase
        [self setGoalLetter: [_arrayOfLowerCaseLetters objectAtIndex: _indexForGoalLetter]];
        [self setGoalPhrase: [_arrayOfPhrases objectAtIndex:_indexForGoalLetter ]];

        //set current level
        [self set_currentLevel: level];
        //[self set_currentLevel: 2];


        //set number of whackholes by level
        [self set_numberOfWhackHoles: [self numberOfWhackHolesByLevel:_currentLevel]];

        //generate size of Letter pool by level
        [self set_numberOfLettersInGameLetterPool:[self numberOfLettersInLetterPoolbyLevel:_currentLevel]];

        ////////////////////////////
        ///  Game letter pool
        ///////////////////////////

        //set up array ton hold the pool of letters
        NSMutableArray *gp = [[NSMutableArray alloc] initWithCapacity:_numberOfLettersInGameLetterPool];
        [self setGameLetterPool: gp];
        [gp release];gp = nil;

        //add the goal letter to this pool
        [_gameLetterPool addObject:_goalLetter];

        int i = 1;

        while (i < _numberOfLettersInGameLetterPool) {
            NSString *letter = [_arrayOfLowerCaseLetters objectAtIndex:(arc4random()%[_arrayOfLowerCaseLetters count])];
            if ([_gameLetterPool containsObject:letter] == false)
            {
                [_gameLetterPool addObject:letter];
                i++;
            }

        }

        NSLog(@"********** Game created  ***************");
        NSLog(@"pool of letters is: %@", [_gameLetterPool description]);
        NSLog(@"****************************************");
        NSLog(@"current goal letter is: %@", _goalLetter);
            NSLog(@"****************************************");
        NSLog(@"current goal phrase is: %@", _goalPhrase);
            NSLog(@"****************************************");

        return self;
    }

-(void)dealloc
{
    [super dealloc];
    [_arrayOfLowerCaseLetters release]; _arrayOfLowerCaseLetters = nil;
    [_arrayOfPhrases release]; _arrayOfPhrases = nil;
    [_goalLetter release];_goalLetter = nil;
    [_goalPhrase release]; _goalPhrase = nil;
    [_gameLetterPool release];_gameLetterPool = nil;
}

【问题讨论】:

    标签: objective-c ios oop


    【解决方案1】:

    第一个问题是[super dealloc] 必须是您在-dealloc 中做的最后一件事。这是因为真正释放内存的是 NSObject 中的 dealloc 方法,所以当你回到它时,你的实例变量指针可能已经是垃圾了。

    其他问题:

    在init中,做self = [super init];超级对象被允许在init上返回一个不同的self指针。

    startNewGameOfLevel:quitTheCurrentGameAndStartNewGame 应该使用属性,而不是裸实例变量。

    -(void)startNewGameOfLevel:(NSInteger)level
        {
            if(![self game])
            {
                Game *g = [[Game alloc]initGamewithLevel:level]; 
                [self setGame:g];
                [g release]; g = nil;// g = nil, not necessary when it's about to go out of scope
            }
    
            [self set_currentlevel:[[self game] _currentLevel]]; // don't use _ to start methods - Apple reserves this convention
    
            // set up popover to show the rounds goal letter
            [self setUpPopOver];
    
        }
    
    -(void)quitTheCurrentGameAndStartNewGame
    {
        [self setGame: nil];
        [self clearGamePlayingField];
         animationStepIndex =  0;
        [self startNewGameOfLevel: _currentlevel];
    }
    

    您的代码主体中可能还有其他问题 - 确保您在构建时启用了静态分析 - 它会捕获其中的许多问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-17
      • 2012-02-27
      • 2013-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-26
      • 1970-01-01
      相关资源
      最近更新 更多