2013-08-26 3 views
1

Я пытаюсь объединить все мои функции определенного класса в файле модели. Например, у меня будет функция fetchContactWithName: (NSString *) name в модели «Contact.h/Contact.m», которую впоследствии вызовет мой диспетчер представлений.Импортировать AppDelegate в модели?

В этом случае было бы плохой идеей импортировать файл AppDelegate.h в файл модели, поскольку мне нужно получить доступ к его управляемому объектуContext?

#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 

ответ

5

На мой взгляд, это плохо идея напрямую спросить другой класс, чтобы получить контекст управляемого объекта. Поскольку

  1. Вы не можете повторно использовать классы в различных проектах (думаю OS X приложение)
  2. Вы не можете получить контакты в другом контексте (думаю, фон импорт)
  3. Вы не можете использовать если метод запрашивает другой класс

Вы должны сообщить об этом методе, в котором он должен извлекаться.
Вместо + (Contact *) fetchContactWithName:(NSString *) name вашего метод подпись должна выглядеть следующим образом:

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

каждый ViewController должен иметь ссылку на NSManagedObjectContext используемого в делегат своего приложения. Вы можете передать ссылку контекста каждому viewController в application:didFinishLaunchingWithOptions:, и каждый раз, когда вы нажимаете или представляете новый viewController, вы передаете ему экземпляр контекста.

Это может показаться, что сейчас много работы, но в какой-то день вы получите выгоду от подхода «рассказать, не спрашивайте».

2

Я думаю, что это плохая идея . Потому что это ООП-уродливый. Что я предлагаю? Вы должны сделать одноэлементный класс 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]; 
+0

Хороший ответ, но singleton - также плохая идея. – pbibergal

+0

@pbibergal, Почему бы и нет? :) –

+0

Синглтон - анти-шаблон. Это так же плохо, как и глобальное. – pbibergal

1

Чтобы получить доступ к вещам из AppDelegate-х класса вы должны

В заголовочном файле

extern AppDelegate *appDelegate; 

и AppDelegate.m файл

AppDelegate *appDelegate = nil; 

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

Теперь в виде модели контроллера импорта AppDelegate файла и вы можете получить доступ к своим методам через свой объект.

Смежные вопросы