首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >导入AppDelegate

导入AppDelegate
EN

Stack Overflow用户
提问于 2011-12-08 03:18:07
回答 7查看 6.5K关注 0票数 18

我经常在AppDelegate中初始化我的模型类变量,以便它们可以被不同的ViewControllers使用,而不需要在类文件之间传递它们的实例。但是,每次我将AppDelegate导入到.m文件中以访问这些变量的数据时,我都觉得自己做错了什么。

这是访问这些变量的正确方式吗?或者我应该做一些不同的事情?

编辑:我的问题不是如何访问变量。我目前使用这行代码来获取我的appDelegate实例:

id appDelegate = [[UIApplication sharedApplication] delegate];

从概念上讲,我想知道这是否是与应用程序的模型类交互的公认方式。在我看来,应用程序的AppDelegate管理着整个应用程序。因此,将这个类导入到应用程序的类链下的其他类中似乎是违反直觉的。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-12-08 03:51:12

这是访问这些变量的正确方式吗?或者我应该做一些不同的事情?

你会发现不同的人对此有不同的看法。我更喜欢的风格是让应用程序委托将必要的信息传递给第一个视图控制器,然后让该视图控制器将其传递给它创建的任何视图控制器,依此类推。这样做的主要原因是,它防止了子视图控制器依赖于他们没有业务知识的东西。

例如,如果您有一些详细信息编辑器,您希望能够向该编辑器传递执行其工作所需的内容。如果你给它提供这些信息,编辑器是完全灵活的--它会编辑你给它的任何信息。如果编辑器知道它应该从某个外部对象获取数据,比如app委托,那么它就失去了一定程度的灵活性--它只能从它知道的东西获取数据。

因此,在app委托中设置数据模型是很好的。但当涉及到提供对模型的访问时,请考虑:tell,不要问。也就是说,让应用程序代理告诉第一个视图控制器要使用哪个模型对象,并让该控制器告诉下一个视图控制器,依此类推。如果你一定要问,你必须知道该问谁,这就是依赖关系开始走向错误方向的地方。

每次我将AppDelegate导入到.m文件中以访问这些变量的数据时,我都觉得自己做错了什么。

相信你的直觉。想想为什么感觉不对劲。

票数 15
EN

Stack Overflow用户

发布于 2012-03-25 01:13:47

我同意有时候AppDelegate似乎是一个合理的地方,把你只想实现一次但可能需要从多个地方实现的东西放在一起。如果这些事情很复杂,为每一个都创建一个单例是很好的,但它确实会给项目带来很多额外的文件和混乱。我也同意这里的大多数答案,即构建对AppDelegate的依赖是一个非常糟糕的设计。

我认为最好的解决方案是创建一个协议!然后,将一个IBOutlet放到一个属性中,以便在需要该函数的每个控制器中执行您需要完成的操作。协议是解耦类的标准objective-C方法。

因此,作为一个例子,我可能有一个数据库URL,我可能需要从一堆地方。也许最好的方法是在此过程中的每一步都设置一个属性。但在某些情况下,这可能会很麻烦,因为使用了股票控制器,而不想对其进行子类化。以下是我的解决方案:

创建文件: MainDatabasePovider.h

代码语言:javascript
复制
#import <Foundation/Foundation.h>
@protocol MainDatabaseProvider <NSObject>
@required
@property (nonatomic, readonly) NSURL *applicationDocumentsDirectory;
@property (nonatomic, weak) NSURL *mainDatabase;
@end

现在,“任何人”(即任何类)只要声明实现了MainDatabaseProvder协议,就可以保证提供上述两个方法。这可以是AppDelegateANY对象。

现在,如果我想让我的AppDelegate提供信息,我要修改AppDelegate.h文件,使其具有:

代码语言:javascript
复制
#import "MainDatabaseProvider.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate, MainDatabaseProvider>
@property (strong, nonatomic) UIWindow *window;
@end

(唯一的变化是将MainDatabaseProvider协议添加到@inteface行,同样可以对您想要提供函数的任何类执行操作)。

在我的AppDelegate.m文件中,我必须编写这两个方法...

代码语言:javascript
复制
@implementation AppDelegate
      ...
@synthesize mainDatabase = _mainDatabase;
      ...
- (NSURL *) applicationDocumentsDirectory {
    return [[[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask] lastObject];
}
- (void) setMainDatabase: (NSURL *) mainDatabase {
    if( _mainDatabase != mainDatabase ) {
        _mainDatabase = mainDatabase;
    }
}
- (NSURL *) mainDatabase {
    if( !_mainDatabase ) {
        NSURL *docURL = self.applicationDocumentsDirectory;
        self.mainDatabase = [docURL URLByAppendingPathComponent: @"My Great Database"];
    }
    return _mainDatabase;
}
      ...
@end

现在,在我的控制器或其他需要获取MainDatabase的类中,我添加了以下内容:

在他们的.h文件中:

代码语言:javascript
复制
#import "MainDatabaseProvider.h"
      ...
@interface myGreatViewController: UIViewController
@property (nonatomic, weak) IBOutlet id <MainDatabaseProvider> mainDatabaseProvider;
      ...
@end

这个属性可以通过控制拖动在以前称为InterfaceBuilder中设置,也可以在prepareForSegue中的代码中设置,或者我喜欢提供一个自定义的getter,以便在我懒惰或健忘的情况下将其默认到AppDelegate中,并且不执行上述任何一种操作。在他们的.m文件中是这样的:

代码语言:javascript
复制
@implementation myGreatViewController
@synthesize mainDatabaseProvider = _mainDatabaseProvider;
      ...
- (id <MainDatabaseProvider>) mainDatabaseProvider {
    id appDelegate = [[UIApplication sharedApplication] delegate];
    if( !_mainDatabaseProvider && [appDelegate conformsToProtocol: @protocol(MainDatabaseProvider)] )
        return appDelegate;
    return _mainDatabaseProvider;
}
// To get the database URL you would just do something like...
- (void) viewWillAppear: (BOOL) animated {
    NSLog( @"In %s the mainDatabaseProvider says the main database is \"%@\"", __func__, self.mainDatabaseProvider.mainDatabase.path );
}

现在可以对任何对象执行操作。我有能力在InterfaceBuilder或我的StoryBoard中设置它(虽然我真的不认为这是一个用户界面项目,所以我通常不会这样做,但这是非常典型的做法),我可以在它加载到prepareForSegue:sender:tableView:didSelectRowAtIndexPath:之前在我的控制器之外的代码中设置它。如果我根本没有设置它,如果我正确地配置了它,它将缺省为AppDelegate

我甚至可以在我年老忘记做事情时,通过更改上面列出的getter来帮助我做一些事情,比如:

代码语言:javascript
复制
- (id <MainDatabaseProvider>) mainDatabaseProvider {
    if( !_mainDatabaseProvider ) {
        id appDelegate = [[UIApplication sharedApplication] delegate];
        if( ![appDelegate conformsToProtocol: @protocol(MainDatabaseProvider)] ) {
            NSLog( @"Hey!! The mainDatabaseProvider is not set and the AppDelegate does not conform to the MainDatabaseProvider protocol. How do you expect me to figure out where the database is!" );
        } else {
            return appDelegate;
    }
    return _mainDatabaseProvider;
}
票数 9
EN

Stack Overflow用户

发布于 2011-12-08 03:39:56

你应该认真避免在任何地方导入AppDelegate,并且你应该觉得每次都做错了什么(+1 )。您实际上是在创建一个Big Ball of Mud,应该重新考虑您的设计。例如,如果您的模型使用CoreData,请考虑使用诸如Magical Panda Active Record之类的框架来检索数据。我在一个企业应用程序上工作,AppDelegate.h只包含在AppDelegate.m中。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8421138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档