Import AppDelegate into models?

I am trying to combine all my functions of a particular class in a model file. For example, I will have the function fetchContactWithName: (NSString *) name in the model "Contact.h / Contact.m", which my view manager will call later.

In this case, would it be a bad idea to import the AppDelegate.h file into the model file, since I need to access its 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 
+1
objective-c core-data
source share
3 answers

In my opinion, it is a bad idea to directly ask another class how to get the context of a managed entity. Because the

  • You cannot reuse your classes in different projects (think of an OS X application)
  • You cannot receive contacts in a different context (think about using a background)
  • You cannot use unit tests if a method requests another class

You must indicate this method in which context it should be selected.
Instead of + (Contact *) fetchContactWithName:(NSString *) name your method signature should look like this:

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

Each viewController must have a reference to the NSManagedObjectContext used in your application. You can pass a context link to each viewController in application:didFinishLaunchingWithOptions: and each time you click or present a new viewController, you pass it a context instance.

Now this may seem like a lot of work, but some day you can take advantage of "tell me, don't ask."

+5
source share

I think this is a bad idea . Because OOP is ugly. What do I suggest? You must make the SharedStorage singleton class as follows:

 + (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]); } } 

And wherever you want to use context, you must create a new NSManagedObjectContext with the same persistentStoreCoordinator :

 self.context = [NSManagedObjectContext new]; self.context.persistentStoreCoordinator = [[SharedStorage sharedStorage] storeCoordinator]; 
+2
source share

To access the AppDelegate class, you need to

In the header file

 extern AppDelegate *appDelegate; 

and in the file AppDelegate.m

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

Now in the model view controller, you import the AppDelegate file, and you can access its methods through your object.

+1
source share

All Articles