How To Pass ManagedObjectContext To Other View Controllers in Special Case - core-data

I have a rootViewController like so:
Header:
#interface ParkingRootViewController : UIViewController {
UINavigationController *navigationController;
UIToolbar *toolbar;
UIBarButtonItem *lastUpdateLabel;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
}
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *lastUpdateLabel;
#property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (nonatomic, readonly) NSString *applicationDocumentsDirectory;
-(IBAction)selectHome:(id)sender;
//-(void)loadOverlays;
-(void)testCoreData;
#end
Implementation:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
//...
[self testCoreData];
//creating label in tool bar
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 150.0f, 20.0f)];
label.text = #"last updated...";
label.textColor = [UIColor colorWithWhite:1.0 alpha:1.0];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
//label.highlightedTextColor = [UIColor colorWithWhite:0.5 alpha:1.0];
//label.highlighted = YES;
label.font = [UIFont systemFontOfSize:13.0];
label.userInteractionEnabled = NO;
[lastUpdateLabel initWithCustomView:label];
[label release];
[self.view addSubview:self.navigationController.view];
[self.navigationController.view setFrame:self.view.frame];
}
But I need to transfer my managedObjectModel to my table view and then to a map view so that the map view can make queries depending on what the user wants to see. I was consulting some apple sample code which looks like(from Recipes):
- (void)applicationDidFinishLaunching:(UIApplication *)application {
recipeListController.managedObjectContext = self.managedObjectContext;
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
I know that is in the appDelegate, but I figure that I can do the same when a row is selected or another view is pushed onto the stack, right? The problem is that I have configured most of my view with a nib which looks like so:
Due to this, I am unable to use a similar strategy that Apple employs to transfer a managedObjectModel to an alternate viewController(in this case PermitListViewController) because I don't access PermitListViewController directly when adding a subview. If anyone has any idea of how I would go about getting my managedObjectModel to my PermitListViewController. Please share! Thanks in advance!
EDIT: I am thinking of placing the managedObjectModel in a singleton class. What are your guys' thoughts on that? Good programming practice? Anything I should be aware of? Thanks.

Why not have the NSManagedObjectContext on the app delegate? Then it would be easily accessible from all your view controllers, and as they are UI they execute on the main thread, and can therefore share the same MOC.

I ended up creating a singleton class for the managedObjectModel using this as a reference (scroll down to "Creating a Singleton Instance").

Related

Problems accessing 1:N relationship in entity

https://github.com/lokming/QuestionBank
I have entities: Bank,Section,Subsection,Set,Question.
I am having problems accessing relationship "NSSet Subsection" in entity Section and getting the message "[UITableViewCell thesubsection]: unrecognized selector sent to instance" from this code
in CRSectionVC.m which fills a tableview cell
- (NSArray *)allQuestions
{
NSSortDescriptor *division = [NSSortDescriptor sortDescriptorWithKey:#"subdivision" ascending:YES];
return [_section2.thesubsection sortedArrayUsingDescriptors:#[division]];
}
I can however access the "NNSet section" relationship in Bank entity using this code
NSSortDescriptor *division2 = [NSSortDescriptor sortDescriptorWithKey:#"division" ascending:YES];
return [self.detailItem2.thesection sortedArrayUsingDescriptors:#[division2]];
_section2 is declared in CRSubsectionVC.h
#property (strong, nonatomic) Section *section2;
The storyboard is
1. CRMasterViewController which displays ‘category’ attribute from Bank entity into a tableview,
Bank.h
#class Section;
#interface Bank : NSManagedObject
#property (nonatomic, retain) NSString * category;
#property (nonatomic, retain) NSSet *thesection;
#end
Bank.m
#implementation Bank
#dynamic category;
#dynamic thesection;
#end
When I tap a ‘category’ I segue and pass a Bank object to CRDetailViewController. I use following code:
NSSortDescriptor *division2 = [NSSortDescriptor sortDescriptorWithKey:#"division" ascending:YES];
return [self.detailItem2.thesection sortedArrayUsingDescriptors:#[division2]];
to fetch section relationship (NSSet *thesection) ‘division’ attribute from Bank into tableview.
Section.h
#class Bank, Subsection;
#interface Section : NSManagedObject
#property (nonatomic, retain) NSString * division;
#property (nonatomic, retain) Bank *bank;
#property (nonatomic, retain) NSSet *thesubsection;
#end
Section.m
#implementation Section
#dynamic division;
#dynamic bank;
#dynamic thesubsection;
#end
If I tap a ‘section’ ’ I segue and pass a Section object to CRSubsectionVC named _section2. When I try to access NSSet *thesubsection to get ‘subdivision’ attribute using code
NSSortDescriptor *division = [NSSortDescriptor sortDescriptorWithKey:#"subdivision"ascending:YES];
return [_section2.thesubsection sortedArrayUsingDescriptors:#[division]];
I get the error [UITableViewCell thesubsection]: unrecognized selector sent to instance. I cannot figure out why automated accessor ‘thesection’ works OK but not ‘thesubsection’ .
Subsection.h
#class Section, Set;
#interface Subsection : NSManagedObject
#property (nonatomic, retain) NSString * subdivision;
#property (nonatomic, retain) Section *section2;
#property (nonatomic, retain) NSSet *set;
#end
Subsection.m
#implementation Subsection
#dynamic subdivision;
#dynamic section2;
#dynamic set;
#end
Fixed the problem. A case of not copying code exactly from working template and understanding core data and table views.

Sorting an NSMutableArrray that contains Arrays?

I have a class called userResults which looks like this:
#import <Foundation/Foundation.h>
#interface userResults : NSObject
#property (nonatomic, strong) NSString *resultsMix;
#property (nonatomic, strong) NSNumber *resultsSaving;
#property (nonatomic, strong) NSNumber *resultsBlendComponent1;
#property (nonatomic, strong) NSNumber *resultsBlendComponent2;
#property (nonatomic, strong) NSNumber *resultsTotalProtein;
#property (nonatomic, strong) NSNumber *resultsPricePerPound;
#property (nonatomic, strong) NSNumber *resultsPricePerPoint;
#end
With a implementation like this:
#import "userResults.h"
#implementation userResults
#end
I will build up multiple values of this in an NSMutableArray called results.
I want to be able to sort the records in results on the *resultsSaving field.
I have populated two arrays, results1 and results2, and stuck them in the larger array, and then I try to sort with this code.
results = [NSMutableArray arrayWithObjects:results1,results2,nil];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"resultsSaving" ascending:YES];
[results sortUsingDescriptors:sort];
Doesn't work. I think that I may have some conceptual problems. Any help would be greatly appreciated.
Bryan
After much scouring of the internet, I found this answer:
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"resultsSaving"
ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
sortedArray = [results sortedArrayUsingDescriptors:sortDescriptors];
What is odd is that you can't do descending, but must give a ascending:NO. That is pretty weird.

CoreData UINavigationController managedObjectContext Error

I have a project that include a combined tabbarController and navigation controller.
sorry,becauce i can't post image, the link of image here:
http://s12.postimage.org/58lbzzxm5/Screen_Shot_2012_11_10_at_9_56_07_AM.png
Code Of NAppDelegate.h:
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface NAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
Code Of NAppDelegate.m:
#import "NAppDelegate.h"
#import "TVC_TabProvince.h"
#implementation NAppDelegate
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
NSArray *arrController = [tabBarController viewControllers];
TVC_TabProvince *controller = (TVC_TabProvince*) [arrController objectAtIndex:0];
controller.managedObjectContext = self.managedObjectContext;
return YES;
}
Before adding the navigation controller, it run without any problem. But when I add this, an error appear:
error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-
[UINavigationController setManagedObjectContext:]: unrecognized selector sent to
instance 0x74b26b0'
The problem is in this line:
TVC_TabProvince *controller = (TVC_TabProvince*) [arrController objectAtIndex:0];
[arrController objectAtIndex:0] is the first view controller of the tab bar controller, so this is the navigation controller and not the TVC_TabProvince controller. The type cast (TVC_TabProvince *) does not change the object, it is still a navigation controller.
So you have to add one step:
NSArray *arrController = [tabBarController viewControllers];
UINavigationController *navController = [arrController objectAtIndex:0];
TVC_TabProvince *controller = [navController. viewControllers objectAtIndex:0];
controller.managedObjectContext = self.managedObjectContext;
It might be more flexible to go the other way around: Instead of "pushing" the managed object context from the application delegate to the table view controller, you "pull" it from the table view controller when needed. So somewhere in "TVC_TabProvince.m" you do
NAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
self.context = [appDelegate managedObjectContext];
Then it does not matter anymore where the table view controller is in the view controller hierarchy. (But that is only a suggestion.)

could not locate an NSManagedObjectModel for entity name "X"

I have this crash error : * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'JourneeDeTravail''
My AppDelegate.h :
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UIWindow *window;
UINavigationController *navigationController;
}
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, retain) UINavigationController *navigationController;
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory;
- (void)saveContext;
#end
My AppDelegate.m :
#import "AppDelegate.h"
#import "TableViewController.h"
#import "ViewController.h"
#implementation AppDelegate
#synthesize window;
#synthesize navigationController;
#synthesize managedObjectContext =_managedObjectContext;
#synthesize managedObjectModel =_managedObjectModel;
#synthesize persistentStoreCoordinator=_persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ViewController *viewController = [[ViewController alloc] init];
viewController.managedObjectContext = [self managedObjectContext];
NSLog(#"AppDelegate VC: %#", managedObjectContext);
return YES;
}
- (void)dealloc {
[super dealloc];
}
#end
And a ViewController.h :
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import "AppDelegate.h"
#interface ViewController : UIViewController{
NSManagedObjectContext *managedObjectContext;
}
#property (retain, nonatomic) IBOutlet UILabel *displayStart;
#property (retain, nonatomic) IBOutlet UILabel *displayEnd;
#property (retain, nonatomic) IBOutlet UITextField *displayResult;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
- (IBAction)SaveTest:(id)sender;
#end
And ViewController.m :
#import "ViewController.h"
#implementation ViewController
#synthesize managedObjectContext;
- (void)viewDidLoad {
if (managedObjectContext == nil) {
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate]managedObjectContext];
NSLog(#"After managedObjectContext VC: %#", managedObjectContext);
}
}
- (IBAction)SaveTest:(id)sender {
NSLog(#"Dans SaveTest : %#", managedObjectContext);
NSLog(#"Context: %#",managedObjectContext);
NSLog(#"PS Coord : %#",managedObjectContext.persistentStoreCoordinator);
NSLog(#"MOM : %#", managedObjectContext.persistentStoreCoordinator.managedObjectModel);
NSLog(#"Entities : %#", [[managedObjectContext.persistentStoreCoordinator.managedObjectModel entities] valueForKey:#"JourneeDeTravail"]);
JourneeDeTravail *journee = (JourneeDeTravail *)[NSEntityDescription insertNewObjectForEntityForName:#"JourneeDeTravail" inManagedObjectContext:managedObjectContext];
}
But when I press SaveTest button it crashes with error log saying all my log lines are (null).
Of course I have an Entity called JourneeDeTravail...
Any idea ? Looks like I don't have a managedObjectContext but I don't know what to do to fix that. Thanks for your help !
Just for those of you who have the same problem : I found the solution when I did this tutorial : http://www.techotopia.com/index.php/An_iOS_5_iPhone_Core_Data_Tutorial
The debugger says all. It can't find the entity. The entity is in your case the storage. No Core Data, no Memory.
In AppDelegate.m in time of applicationDidFinishLaunching try to instantiate a storage class. Thats the entitiy the ManageObjectModel search for.
like: myMainThreadStorage = [[StorageClass alloc] init];
Or I have completely misunderstood the last 6 hours of studying my problem and solved it with a later [super viewDidLoad]

self.navigationController value gets null in Tabbar VIew

I have a navigation controller as the root view controller. I have a UIView then a UITableView, then again a UITableView, then a TabbarView and each of my tabbarview is a hierarchy of views. Now my problem is that I am able to get the value of self.navigationcontroller till the last UITableView but the value gets null in the TabbarView. Now is there a way I can access the value in the Tabbarview. Do I have to create a new navigation controller for each tabs in the tabbarview and then assign the root navigation controller value to it?
My below code does not work,
The last controller where I can get the value of the navigationController is AssignmentViewController.
Code from AssignmentViewController:
- (void)viewDidLoad {
UITransTabViewController *transtvController = [[UITransTabViewController alloc] initWithNibName:#"TransTabViewController" bundle:nil];
self.transtabViewController = transtvController;
transtvController.naviController=self.navigationController;
[transtvController release];
}
In my UITranTabViewController.h I have the below code,
#interface UITransTabViewController : UIViewController <UITabBarDelegate> {
NSArray *viewControllers;
IBOutlet UITabBar *tabBar;
IBOutlet UITabBarItem *arrivalsTabBarItem;
IBOutlet UITabBarItem *departuresTabBarItem;
UIViewController *selectedViewController;
UINavigationController *naviController;
}
#property (nonatomic, retain) NSArray *viewControllers;
#property (nonatomic, retain) IBOutlet UITabBar *tabBar;
#property (nonatomic, retain) IBOutlet UITabBarItem *arrivalsTabBarItem;
#property (nonatomic, retain) IBOutlet UITabBarItem *departuresTabBarItem;
#property (nonatomic, retain) UIViewController *selectedViewController;
#property (nonatomic, retain) IBOutlet UINavigationController *naviController;
I am trying to set the value of naviController from the AssignmentViewController, but still I get the
NSLog(#"MY NAV CONTROLLER IN TRANSTABVIEWCONTROLLER IS = %#", self.naviController);
value as NULL.

Resources