在Cocoa Objective C中的类之间发送数据

时间:2010-11-18 00:03:27

标签: objective-c cocoa cocoa-touch class

我大约一个月前开始为iPhone做编程,并且发现该网站非常有用。所以我虽然有人可以帮助我。

我想我理解@property和@synthesise如何工作和使用setter和getter的基础知识,但我遇到了问题。

假设我有3个类:函数,Class1和Class2。

函数是一个包含所有数据的类,Class1和Class2从中读取数据并将新数据(修改数据)写入其中。但是Class1和Class2都会创建自己的函数实例,因为它基本上只是数据的蓝图。

因此,如果Class1写入或“设置”一些数据(比方说)5到函数而Class2'得到'它,Class2将返回0,因为Class1只向其函数实例写了5,而Class2看不到。

我想首先,是吗?其次,我该怎么做才能让Class1和Class2看到相同的数据来获取和设置。

感谢您的帮助。我意识到这可能包括一个我还没有学过的话题,但是如果是这样的话,我很想知道它是什么,所以我可以把它搞定。

4 个答案:

答案 0 :(得分:6)

您有许多选项可以确保Class1和Class2使用“共享对象”的相同实例。

  1. 从外部将相同的实例快速传递给Class1和Class2,而不是允许Class1和Class2自己创建实例;或
  2. 为Functions类提供单例初始值设定项,然后确保Class1和Class2使用它;或
  3. 使用称为注册表模式的设计模式,并确保Class1和Class2从注册表中获取其函数类的实例;或
  4. 使用依赖注入(复杂)。
  5. 场景(1)是最容易理解的,因为它完全像这样:

    Functions *funcs = [[Functions alloc] init];
    
    Class1 *obj1 = [[Class1 alloc] initWithFunctions:funcs];
    Class2 *obj2 = [[Class2 alloc] initWithFunctions:funcs];
    /* or alternatively use setters after initialization */
    

    场景(2)是下一个最简单的场景,非常常见。 Cocoa为其中的许多类提供单例初始化器。每当你看到+shared...作为初始化程序的前缀时,它可能会返回一个单例。

    @implementation Functions
    
    +(id)sharedFunctions {
      static Functions *sharedFunctions = nil;
    
      @synchronized(self) {
        if (sharedFunctions == nil) {
          sharedFunctions = [[self alloc] init];
        }
    
        return sharedFunctions;
      }
    }
    
    @end
    

    静态变量只初始化一次,这意味着您可以使用检查对象的初始值(仅发生一次)来懒惰地将对象的实例加载到其中。对该方法的每次后续调用都会返回相同的实例。

    Functions *f1 = [Functions sharedFunctions];
    Functions *f2 = [Functions sharedFunctions];
    
    /* f1 == f2; */ // always
    

    与其他语言相比,在目标C中看不到选项(3),它实现了与单身人士相同的目标。这个想法是你有一个可以通过键查找的对象字典。需要访问注册表中项目的所有内容只是向注册表询问其自己的实例。通常,注册表本身就是单身人士。

    选项(4),依赖注入,实际上是一个非常优雅的解决方案,以额外的复杂性为代价获得了许多好处。好处来自这样一个事实:您已经确保依赖关系总是松散耦合(这使得交换实现,并且单独测试依赖关系变得更加简单)。复杂性来自于检索所需内容实例的非标准机制。

    依赖注入围绕着没有对象实例化自己的依赖关系的想法。而不是依赖其他东西来提供这些依赖。那个“别的东西”被称为依赖注入容器。依赖注入容器实际上是注册表模式之上的一个层,因为容器将保存依赖项的预构建实例,或者它将知道如何实例化新实例。

    在最简单的情况下,依赖注入正是我在选项(1)中演示的内容。您甚至不需要依赖注入容器来实现此目的。

    提高了复杂程度,依赖注入带来了DI容器的概念,它封装了许多现有的设计模式(注册表,如选项(3)所示,单例(可能,但不严格)和工厂(知道如何制作它管理的对象的新实例)。

    演示DI容器的完整实现可能超出了这个问题的范围,但从公共接口的角度来看,一个实现可能如下所示:

    DIContainer *container = [DIContainer sharedContainer];
    
    [container registerClass:[ClassA class]];
    [container registerClass:[ClassB class]];
    [container registerDependentProperty:@selector(setClassA:)
                          withInstanceOf:[ClassA class]
                                forClass:[ClassB class]];
    
    ClassB *obj = [container makeInstanceOfClass:[ClassB class]];
    NSLog(@"ClassB's -classA type = %@", [[obj classA] class]);
    

    我只是在这篇文章的中间输入了我的头顶,所以不要认为它是100%准确,但你得到了这个概念。已经指示容器初始化ClassB的实例时,它必须使用-setClassA:的实例调用ClassA,它也根据容器中定义的规则进行初始化(在这种情况下,不是ClassA的依赖项,所以它只返回一个普通的实例。

    如果您不再接受此答案,请记住选项(1)和(2);)

答案 1 :(得分:1)

您需要阅读“可可基础指南”。与您的问题相关的部分称为Communicating with Objects

答案 2 :(得分:0)

这通常是关于面向对象编程的一个问题,但该解决方案也适用于Objective-C。你想要做的是创建一个函数实例。该实例应该在Class1和Class2的实例之间共享。

Functions *f = [[Functions alloc] init];
Class1 *c1 = [[Class1 alloc] init];
Class2 *c2 = [[Class2 alloc] init];
// set the value of a instance variable of f to the value of aValue from c1
[f setSomeValue:[c1 aValue]];
// now change it to c2's aValue
[f setSomeValue:[c2 aValue]];

答案 3 :(得分:0)

有很多在线参考文献,但我发现这本书是一个很好的资产。由Stephen G. Kochan编写的Objective-C 2.0(第2版)编程。这是一个很好的起点。