Ios 导入AppDelegate

Ios 导入AppDelegate,ios,cocoa-touch,model-view-controller,dependencies,uiapplicationdelegate,Ios,Cocoa Touch,Model View Controller,Dependencies,Uiapplicationdelegate,我经常在AppDelegate中初始化模型类变量,以便不同的ViewController可以使用它们,而无需跨类文件传递它们的实例。但是,每次我将AppDelegate导入到.m文件中以访问这些变量的数据时,我都觉得自己做错了什么 这是访问这些变量的正确方法还是我应该做些不同的事情 编辑: 我的问题不是如何访问变量。我当前使用这行代码获取appDelegate实例: id appDelegate=[[UIApplication sharedApplication]委托] 从概念上讲,我想知道这是

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

这是访问这些变量的正确方法还是我应该做些不同的事情

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

id appDelegate=[[UIApplication sharedApplication]委托]


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

我也在导入它们,并像这样使用它:

 AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
 [delegate variable];

另一种方法是使用单例。

将此方法放在AppDelegate类中

+ (AppDelegate *)get {
    return (AppDelegate *) [[UIApplication sharedApplication] delegate];
}
当您需要调用AppDelegate时,请使用:

[AppDelegate get];

您应该认真避免在任何地方导入AppDelegate,并且每次导入AppDelegate时都会感觉自己做错了什么(+1)。您实际上是在创建一个新的应用程序,应该重新考虑您的设计。例如,如果你在模型中使用CaleDATA,那么考虑一个框架,比如检索数据。我在一个企业应用程序上工作,
AppDelegate.h
仅包含在
AppDelegate.m

这是访问这些变量的正确方法还是我应该 你在做不同的事情吗

你会发现不同的人对此有不同的看法。我喜欢的样式是让应用程序委托将必要的信息传递给第一个视图控制器,并让该视图控制器将其传递给它创建的任何视图控制器,依此类推。这样做的主要原因是它防止子视图控制器依赖于他们不必知道的事情

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

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

每次我将AppDelegate导入.m文件以访问这些 变量的数据我觉得我做错了什么


相信这种本能。想想为什么感觉不对。

看看单身人士。它们可以是一种更优雅的方式来管理全球数据。

这是一种方式,是的,但它不是很优雅。单件也是一种方式,是的,但不是很优雅:)-如果你不得不模仿所有的单件,那么测试你的代码确实不容易。 相反,我可能会做的是为一个服务提供者提供一个单例,并向这个服务提供者请求一个实例,即您的模型提供者

比如说,您的服务提供者类是单例的,您需要访问模型以查看用户详细信息。我会按以下方式做:

JMUserDetailModel *myModel = [[[JMServiceProvider sharedInstance] modelProvider] userDetailModel];
这意味着您将创建一个JMServiceProvider类来注册服务,并能够检索这些服务。这些服务的行为有点像单例,但是如果您需要对代码进行单元测试,那么注册一个与原始服务相同的不同服务只是小菜一碟

希望这能回答你的问题


编辑:阅读这篇文章:-这篇文章也很好地解释了面向服务的体系结构…

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

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

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

创建文件:maindabasepovider.h

#import <Foundation/Foundation.h>
@protocol MainDatabaseProvider <NSObject>
@required
@property (nonatomic, readonly) NSURL *applicationDocumentsDirectory;
@property (nonatomic, weak) NSURL *mainDatabase;
@end
(唯一的更改是将MainDatabaseProvider协议添加到
@inteface
行中,同样可以对任何要提供该函数的类执行此操作)

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

@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
现在,在需要获取Main数据库的控制器或其他类中,我添加了以下内容:

在他们的
.h
文件中:

#import "MainDatabaseProvider.h"
      ...
@interface myGreatViewController: UIViewController
@property (nonatomic, weak) IBOutlet id <MainDatabaseProvider> mainDatabaseProvider;
      ...
@end
现在,
maindabaseprovider
可以是任何对象。我可以在
InterfaceBuilder
或我的
情节提要
(
#import "MainDatabaseProvider.h"
      ...
@interface myGreatViewController: UIViewController
@property (nonatomic, weak) IBOutlet id <MainDatabaseProvider> mainDatabaseProvider;
      ...
@end
@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 );
}
- (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;
}