将AppDelegate导入模型?

时间:2013-08-26 07:02:39

标签: objective-c core-data

我正在尝试统一模型文件中特定类的所有函数。例如,我在模型'Contact.h / Contact.m'中有一个函数fetchContactWithName:(NSString *)name,我的viewcontroller随后会调用它。

在这种情况下,将AppDelegate.h文件导入到模型文件中是不是一个坏主意,因为我需要访问它的managedObjectContext?

#import "AppDelegate.h"

@implementation Contact

...

+ (Contact *) fetchContactWithName:(NSString *) name {
  AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];

  NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
  NSEntityDescription *entity = [NSEntityDescription entityForName:@"Contact" inManagedObjectContext:delegate.managedObjectContext];
  [fetchRequest setEntity:entity];

  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", name];
  [fetchRequest setPredicate:predicate];

  NSError *error = nil;
  NSArray *fetchedObjects = [delegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];

  Contact *fetchedContact;
  for(Contact *contact in fetchedObjects) {
      fetchedContact = contact;
  }

  if(fetchedContact != nil) {
      return fetchedContact;
  } else {
      return nil;
  }

}
@end

3 个答案:

答案 0 :(得分:5)

在我看来,直接要求另一个类来获取托管对象上下文是个坏主意。因为

  1. 您无法在不同的项目中重复使用您的课程(想想OS X应用程序)
  2. 您无法在不同的上下文中获取联系人(想想后台导入)
  3. 如果方法要求其他类
  4. ,则不能使用单元测试

    你应该告诉这个方法它应该在哪个上下文中获取 而不是+ (Contact *) fetchContactWithName:(NSString *) name您的方法签名应该如下所示:

    + (Contact *)fetchContactWithName:(NSString *)name inManagedObjectContext:(NSManagedObjectContext *)context
    

    每个viewController都应该引用您的app delegate中使用的NSManagedObjectContext。您可以将上下文的引用传递给application:didFinishLaunchingWithOptions:中的每个viewController,每次推送或呈现新的viewController时,都会将上下文实例传递给它。

    这可能看起来像现在很多工作,但有一天你会受益于“告诉,不要问”的方法。

答案 1 :(得分:2)

我认为,这是坏主意。因为它是OOP丑陋的。 我有什么建议? 你应该像这样制作一个单独的类SharedStorage

+ (SharedStorage*)sharedStorage
{
    static SharedStorage* _sharedStorage = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedStorage = [[self alloc] init];
    });
    return _sharedStorage;
}

- (SharedStorage*)init {
    self = [super init];
    if (self)
    {
        [self setupPersistentStoreCoordinator];
    }
    return self;
}

- (NSManagedObjectModel*)__managedObjectModel
{
    if (_managedObjectModel_ == nil)
    {
        NSBundle *mainBundle = [NSBundle mainBundle];
        NSURL *modelURL = [mainBundle URLForResource:@"yourURL" withExtension:@"momd"];
        _managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    }
    return _managedObjectModel_;
}


- (void)setupPersistentStoreCoordinator
{
    if (_storeCoordinator != nil)
        return;
    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"YourDB.sqlite"];
    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
    NSError *error;
    _storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self __managedObjectModel]];
    if (![_storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }
}

在您想要使用上下文的任何地方,您必须使用相同的NSManagedObjectContext创建新的persistentStoreCoordinator

self.context = [NSManagedObjectContext new];
    self.context.persistentStoreCoordinator = [[SharedStorage sharedStorage] storeCoordinator];

答案 2 :(得分:1)

要访问AppDelegate课程的内容,您需要

在头文件

extern AppDelegate *appDelegate; 

并在AppDelegate.m文件中

AppDelegate *appDelegate = nil;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
}

现在在模型视图控制器中导入AppDelegate文件,您可以通过其对象访问其方法。