【问题标题】:Sending data between classes in Cocoa Objective C在 Cocoa Objective C 中的类之间发送数据
【发布时间】:2011-05-11 18:16:40
【问题描述】:

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

我想我了解@property 和@synthesise 如何工作以及使用setter 和getter 的基础知识,但我有一个问题。

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

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

因此,如果 Class1 将某些数据(假设)5 写入或“设置”到 Functions 并且 Class2“获取”它,Class2 将返回 0,因为 Class1 仅将 5 写入其 Functions 实例,而 Class2 看不到。

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

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

【问题讨论】:

    标签: objective-c cocoa cocoa-touch class


    【解决方案1】:

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

    1. 明确将同一个实例从外部传递给Class1和Class2,而不是让Class1和Class2自己创建实例;或
    2. 为 Functions 类提供一个单例初始化器,然后确保 Class1 和 Class2 使用它;或
    3. 使用一种称为注册表模式的设计模式,并确保 Class1 和 Class2 从注册表中获取其函数类的实例;或
    4. 使用依赖注入(复杂)。

    场景 (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
    

    与其他语言相比,选项 (3) 在 Objective-C 中的使用并不多,它实现的目标与单例几乎相同。这个想法是你有一个可以按键查找的对象字典。需要访问注册表中项目的所有内容都只向注册表询问其自己的实例。通常注册表本身是一个单例。

    选项(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) ;)

    【讨论】:

    • 干杯,这真的很有用。我选择了选项 2,效果很好。选项 3 和 4 有点过头了,但我会在我睡了一点后明天重新阅读它们。早上可能会更有意义。不过感谢您的帮助,非常有用。 :-D
    • 没问题,我认为您选择选项 (2) 是一个不错的选择。选项(1)在“技术上”是最好的,因为单例在许多开发人员中的名声有些不好,因为它很难被测试(不干净的测试环境)。但是,正确使用它是完全没问题的。实际上,由于 Objective-C 不像其他语言那样有一个独占的初始化器/构造器,所以单例并不是 100% 强制的,所以在任何情况下都可以在测试中解决它。选项 3 很简单,但是选项 (4) 是一个即使是经验丰富的开发人员也会感到困惑的主题。
    • 我知道这个问题很老,但这完全帮助了我。 +1
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这实际上是一个关于一般面向对象编程的问题,但该解决方案也适用于 Objective-C。您要做的是创建一个 Functions 实例。该实例应在 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]];
      

      【讨论】:

      • 好的,这很有道理。所以我猜你只会将带有 Class1 的位放在 Class1 文件中,并且只将带有 Class2 的位放在 Class2 文件中。虽然 init Functions 实例同时出现在两者中?对不起,如果我重复了一些事情,但我一直在一遍又一遍地思考这些东西,我的脑子有点糊涂了。
      【解决方案4】:

      那里有很多在线参考资料,但我发现这本书是一笔巨大的财富。 Stephen G. Kochan 的 Objective-C 2.0 编程(第二版)。这是一个很好的起点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-29
        • 1970-01-01
        • 1970-01-01
        • 2016-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多