从另一个类访问类的实例变量(NSMutable Array)

时间:2010-10-20 20:28:48

标签: iphone objective-c variables instance delegation

Obj C的新手和一般的编程 - 从这个网站上学到了很多,非常感谢大家的贡献。

我的情况如下(编写iPhone游戏,解释有趣的名字)

在我的主游戏中(在我的视图控制器中)如果满足某个条件我创造了一个敌人 - 樱桃炸弹

if (bounceCounterGlobal % 2 == 0 && bounceCounterGlobal > 1 && cherryBombSwitch == 0){
    [self addCherryBomb];
}

addCherryBomb方法如下:

-(void) addCherryBomb{
    CherryBomb *myCherryBomb = [[CherryBomb alloc] init];
    [cherryBombArray insertObject:myCherryBomb atIndex:0];
    [myCherryBomb release];
    [[cherryBombArray objectAtIndex:0] initializeCherryBomb];
     [self.view addSubview:[[cherryBombArray objectAtIndex:0] cherryBombView]];
    cherryBombSwitch = 1;
}

CherryBomb头文件很简短:

#import <Foundation/Foundation.h>
#import "SimpleGameViewController.h"

    @interface CherryBomb : NSObject {

        UIImageView *cherryBombView;
        NSTimer *cherryBombDetonateTimer;
        NSTimer *cherryBombMoveTimer;
    }

    @property (nonatomic, retain) UIView *cherryBombView;

    -(void) initializeCherryBomb;
    -(void) detonateCherryBomb;
    -(void) moveCherryBomb;

    @end

我想做的是当樱桃炸弹爆炸时(在cherryBomb对象中确定),我希望该对象从视图控制器的ivar中的cherryBombArray中移除。

我尝试调用一个视图控制器类方法来执行此操作 - 但我无法访问视图控制器的ivars(因为它是一个类方法)。我不知道如何与视图控制器类进行通信,告诉它删除爆炸对象。

@implementation CherryBomb
...
-(void) detonateCherryBomb{
    NSLog(@"KABOOM!");
    cherryBombDetonateTimer = nil;
    [cherryBombMoveTimer invalidate];
    [cherryBombView removeFromSuperview];
    //I would like to remove this object from the view controller's cherryBombArray
}
@end

非常感谢您的帮助。提前谢谢!

4 个答案:

答案 0 :(得分:2)

我建议您创建一些可以处理所有游戏逻辑的“环境”对象。

CherryBomb不应该处理它的爆炸。 cherryBomb可以存储许多信息(爆炸的大小,爆炸的类型等),但是cherryBomb对其他“东西”(角色,炸弹,等等)的影响不应该由ch​​erryBomb本身计算。

我不习惯游戏编程,但架构/设计的这个方面很常见:每个对象/类都有自己的职责。

cherryBomb代表了一个炸弹,不再是(而不是“图形”方面)。

Environnement代表了当下的“世界”,并模拟了世界各个元素之间的行动/互动。

关于设计游戏的最佳方式还有很多话要说......

无论如何,为了给你的问题一个答案,你仍然可以使用“事件”。炸弹可以向你的控制器发送一条消息告诉他:“我爆炸了,把我移开了。”

在炸弹中:

[[NSNotificationCenter defaultCenter] postNotificationName:@"kaBOOM" 
                                                    object:self];

在控制器中:

[NSNotificationCenter defaultCenter] addObserver:self
                                        selector:@selector(methodToCallWhenKaBOOM) 
                                            name:@"kaBOOM" 
                                          object:nil];

- (void)methodToCallWhenKaBOOM:(NSNotification *)note
{
    // do stuffs
}

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

答案 1 :(得分:1)

有很多方法可以做到这一点,你可能想要在控制器和模型方面考虑这里的确切分工。如果你来回呼叫太多,事情就会变得非常严重。

但是,如果不了解所有这些,允许一个对象访问另一个对象需要做的基本事情是给第一个对象提供第二个对象。

在这种情况下,您实际上是在视图控制器中创建CherryBomb,因此在此处传递引用很容易。给你的CherryBomb班这样的另一个ivar:

SimpleGameViewController* cherryBombViewController;

修改CherryBomb,以便init方法或initializeCherryBomb方法(这些可能应该只是一个方法,顺便说一句)获取这样的指针并将其分配给ivar:

- (void) initializeCherryBomb:(SimpleGameViewController*)vc
{
    // ... whatever other stuff you do in here, plus something like:
    cherryBombViewController = vc;
}

当您拨打此电话时,请将self作为vc参数传递给您。然后,当你的炸弹爆炸时,它可以调用你在控制器上添加的一些方法来移除它自己:

[cherryBombViewController handleDetonationOfCherryBomb:self];

请注意,绝对不应直接访问控制器的数组 - 这是炸弹应该不知道的实现细节。在简单的情况下,您可以在控制结构中稍微邋in,但从不拧紧您的封装。

答案 2 :(得分:0)

阅读MVC设计模式。如果您发现需要在视图之间共享的ivars,它们应该可以进入更高级别的Model对象(MVC的M),而不是让某些视图达到其他视图的ivars。然后,可以将指向此Model对象的指针传递给需要访问它的所有视图对象。

答案 3 :(得分:0)

我认为这是key value observing的一个很好的应用。你需要一个代表其状态的樱桃炸弹的属性,例如。

@property (assign) BOOL isExploded;

任何对樱桃炸弹是否爆炸感兴趣的物体都会在isExploded属性上为KVO注册。例如,视图控制器可能会执行以下操作:

[cherryBomb addObserver: self
             forKeyPath: @"isExploded"
                options: ....
                context: ....];

并在-observeValueForKeyPath:ofObject:change:context:中为视图控制器从阵列中移除樱桃炸弹。

您的引爆方法执行以下操作以及当前正在执行的所有操作:

[self setExploded: YES];