【问题标题】:iPhone proper usage of Application DelegateiPhone 正确使用 Application Delegate
【发布时间】:2010-09-25 05:19:11
【问题描述】:

我希望能够通过我的应用程序中的任何位置引用某些状态/对象。例如,用户登录到他们的应用程序,我需要调用 Web 服务并检索用户信息。然后我希望能够从应用程序中的任何位置访问这些信息,如下所示:

myAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
user = delegate.u;

在应用程序委托中将实例变量设置为用户对象并在需要时从那里引用它是一种糟糕的处理方式吗?我通常在用户登录时将其设置在那里。

想听听专业人士如何处理这个问题。

【问题讨论】:

    标签: iphone objective-c cocoa-touch


    【解决方案1】:

    我认为您的方法没有任何问题。我通常使用单例来处理这种情况:

    // MyCommon.h:
    @interface MyCommon
    class MyCommon : NSObject
    {
        int user;
    };
    
    @property(assign) int user;
    
    + (MyCommon *)singleton;
    
    @end
    
    // MyCommon.m:
    @implementation MyCommon
    
    static MyCommon * MyCommon_Singleton = nil;
    
    + (MyCommon *)singleton
    {
        if (nil == MyCommon_Singleton)
        {
            MyCommon_Singleton = [[MyCommon_Singleton alloc] init];
        }
    
        return MyCommon_Singleton;
    }
    @end

    MyCommon 单例随后在我的应用程序中的任何位置使用,如下所示:

    int user = [MyCommon singleton].user;

    【讨论】:

    • 我在几年前发布了这篇文章,从那时起我学到了一些东西。关于单例,要意识到的重要一点是它们与全局变量没有什么不同。这并不一定意味着在所有情况下都应避免使用它们,而只是意味着它们具有相同的缺点,尤其是在适当封装和易于测试方面。例如,在这种情况下,如果不首先设置全局 user 值,就很难单独测试依赖于 [MyCommon singleton] 的各个类。
    • 全局可访问的单例的一个很好的替代方法是使用依赖注入。您基本上在您的应用程序委托中创建相同的MyCommon 对象,然后将其传递给任何需要它的子对象,然后继续此过程直至您的对象层次结构。这会增加一些工作量,但会导致程序更加面向对象,更易于维护和调试。
    • 要了解 SO 社区对此事的看法,这里有一个链接指向我在开始转换时询问的关于单身人士的问题:stackoverflow.com/questions/474613
    【解决方案2】:

    通常,您会向应用程序的控制器询问此信息,它会负责了解如何在任何存在的数据模型中存储/查找它。您的应用程序的控制器可能与应用程序委托相同,也可能不同(在大多数简单的应用程序中,它是相同的)。

    【讨论】:

      【解决方案3】:

      通常,只有在以下情况下,您才应该将事物连接到应用委托:

      • 从与应用委托相同的 NIB 文件创建(即单窗口界面中的静态 UI 元素)
      • 与通过应用程序委托传递的应用程序级事件处理相关联(如首选项窗口的菜单项)

      对于其他所有内容,您应该创建一个单例来管理对它们的访问。

      Jason Coco 建议通过应用程序控制器进行路由。在我的程序中,我通常会避免这种情况,因为我认为它把太多的责任放在了顶层——我认为事情应该尽可能地自我管理,并且只有在需要同行之间的协调时才应该使用更高级别的管理——级别模块。

      我不会链接我自己的博客,但如果你用 Google 搜索我和单身人士,你可能会发现我写的一篇更详细的帖子。

      【讨论】:

      • 谢谢马特。介意我问你在说首选项窗口的菜单项时具体指的是什么?
      • 很想阅读您的博客 Matt,但遗憾的是目前还没有。希望这是暂时的。
      • 我对在 Cocoa 代码中使用单例的想法缺乏批评感到失望。单例在某种意义上很简单而且“干净”(没有应用程序委托形式的全局上帝类),但它们根本不适合测试。大多数经验丰富的 TDD 从业者会推荐使用 DI,也许使用构造函数参数来传递状态或状态对象。我正在寻找一些关于如何在 Cocoa 中最好地实现这一点的信息,但我发现的只是告诉我们使用单例模式的建议。
      • @jkp:单例可能很难进行单元测试,但不要将其解释为单例不好。实际上反过来是正确的:这是单元测试的一个缺陷,它只在命令模式实现上表现出色,并且为每个单元测试设置状态机(如常见的桌面应用程序模型)很麻烦。为应用程序状态的每个元素使用方法参数,只是为了避免单例,是一种可怕的设计模式。正确的解决方案是在调用测试之前像模拟任何其他对象(更改 sharedInstance 方法返回的对象)一样交换模拟单例。
      【解决方案4】:

      马特有点太谦虚了。他在这个主题上的帖子是我读过的最好的帖子之一,值得一个链接。 http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-23
        相关资源
        最近更新 更多