2013-08-26 53 views
1

我想統一模型文件中特定類的所有功能。例如,我會在模型'Contact.h/Contact.m'中有一個函數fetchContactWithName:(NSString *)名稱,我的viewcontroller隨後會調用它。將AppDelegate導入模型?

在這種情況下,將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 

回答

5

在我看來這是一個壞想法直接請求不同的類來獲取您的託管對象上下文。由於

  1. 你真的不能重複使用在不同的項目你的類(認爲OS X的應用程序)
  2. 不能在不同的上下文中提取通訊錄(認爲背景進口)
  3. 不能使用單元測試方法是否詢問其他類

您應該告訴此方法應該在哪個上下文中獲取。
而不是+ (Contact *) fetchContactWithName:(NSString *) name你的方法簽名應該是這樣的:

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

各自的viewController應該在你的應用程序代理使用的NSManagedObjectContext的參考。您可以將上下文的引用傳遞給application:didFinishLaunchingWithOptions:中的每個viewController,並且每次您推送或呈現新的viewController時,都會將該上下文實例傳遞給它。

這可能看起來像很多工作,但有一天你會從「告訴,不要問」的方法中受益。

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]; 
+0

好的答案,但單身也是一個壞主意。 – 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文件和你可以通過它的對象訪問它的方法。