【问题标题】:Accessing a class' instance variable (NSMutable Array) from another class从另一个类访问一个类的实例变量(NSMutable Array)
【发布时间】:2011-04-28 06:37:54
【问题描述】:

刚接触 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 对象中确定),我希望该对象从cherryBombArray 中移除,它是视图控制器的一个ivar。

我尝试调用视图控制器类方法来执行此操作 - 但我无法访问视图控制器的 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

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

【问题讨论】:

    标签: iphone objective-c variables instance delegation


    【解决方案1】:

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

    cherryBomb 不应该处理它的爆炸。 cherryBomb 可以存储许多信息(爆炸的大小、爆炸的类型等),但是cherryBomb 对其他“事物”(字符、炸弹等)的影响不应由cherryBomb 本身计算。

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

    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

    【讨论】:

      【解决方案2】:

      有多种方法可以做到这一点,您可能需要考虑这里的确切分工,就控制器和模型而言。如果您来回调用太多,事情可能会变得相当意大利面。

      但是,在不涉及所有这些的情况下,允许一个对象访问另一个对象所需做的基本事情是为第一个对象提供对第二个对象的引用。

      在这种情况下,您实际上是在视图控制器中创建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];
      

      请注意,您绝对不应直接访问控制器的数组——这是您的炸弹不应该知道的实现细节。在简单的情况下,您可以避免在控制结构中稍稍马虎,但永远不要搞砸你的封装。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          @property (assign) BOOL isExploded;
          

          任何对樱桃炸弹是否爆炸感兴趣的对象都会在 isExploded 属性上为 KVO 注册自己。例如视图控制器可能会这样做:

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

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

          你的 detonate 方法和它目前正在做的其他事情一样做以下事情:

          [self setExploded: YES];
          

          【讨论】:

            猜你喜欢
            • 2012-05-21
            • 1970-01-01
            • 2020-04-14
            • 2013-10-28
            • 1970-01-01
            • 1970-01-01
            • 2012-01-23
            • 1970-01-01
            相关资源
            最近更新 更多