1

我正在尝试统一模型文件中特定类的所有功能。例如,我将在模型“Contact.h/Contact.m”中有一个函数 fetchContactWithName:(NSString *)name,我的视图控制器随后会调用它。

在这种情况下,将 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
4

3 回答 3

5

在我看来,直接询问不同的类来获取您的托管对象上下文是一个坏主意。因为

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

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

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

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

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

于 2013-08-26T07:13:53.607 回答
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]);
    }
}

在任何你想使用上下文的地方,你都必须创建一个新NSManagedObjectContextpersistentStoreCoordinator

self.context = [NSManagedObjectContext new];
    self.context.persistentStoreCoordinator = [[SharedStorage sharedStorage] storeCoordinator];
于 2013-08-26T07:13:26.603 回答
1

要访问AppDelegate类的东西,你需要

在头文件中

extern AppDelegate *appDelegate; 

并在 AppDelegate.m 文件中

AppDelegate *appDelegate = nil;

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

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

于 2013-08-26T07:15:14.293 回答