I have a TableViewController using the CoreData database.
I have another UIviewController from which I want to read the TableViewController's database.
What I did was as follow.
//In UIviewController
-(NSArray *)fetchRecordedDatainsqldatabase
{
// construct a fetch request
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
//[fetchRequest setFetchBatchSize:20];
// Create the sort descriptors array.
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"descript" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:descriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// return the result of executing the fetch request
return [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];}
I have a property of
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
But managedObjectContext is always nil, at the line
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList"
inManagedObjectContext:self.managedObjectContext];
So the program is always crash when it reaches to that line.
What could be the problem?
Generally you can use the managedObjectContext provided to you in the stub code in AppDelegate. If thats the case you can use:
AppDelegate *appD = [[UIApplication sharedApplication] delegate];
then instead of the line:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList"
inManagedObjectContext:self.managedObjectContext];
use:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrackerList"
inManagedObjectContext:appD.managedObjectContext];
and you should replace the return statement to this:
return [appD.managedObjectContext executeFetchRequest:fetchRequest error:&error];
If you are creating your own NSManagedObjectContext object, then you should be setting its persistentStoreCoordinator (which in turns need the managed object model and set the persistent store type).
You can see how to do all this in AppDelegate.m , if you have checked 'use core-data' when creating the project.
Anyway in your case, you already are using a managedObjectContext successfully in your first view controller. So you just need to get the same object over in the second view controller.
For your method to work, you just have to add one line at the top of the code block you provided:
self.managedObjectContext = [[[UIApplication sharedApplication] delegate] managedObjectContext];
Managed Object Context needs to be initialized with a Persistent Store Coordinator and which needs a Managed Object Model. XCode used to provide a boiler plate code for all these implementation in AppDelegate.
As an alternative solution you can try using MagicalRecord
You can set up core data by
[MagicalRecord setupCoreDataStackWithStoreNamed:#"Database.sqlite"];
And you can fetch all the trackerlist values in a context by
NSManagedObjectContext *context = [NSManagedObjectContext defaultContext];
[TrackerList findAllSortedBy:#"descript" ascending:YES inContext:context];
Following link would guide you better
How to make programming in Core Data pleasant
Related
When I was in use coredata multiple entities at the same time the request data will cause this phenomenon?
I couldn't find the reason, want to ask whether this reason
The following method is one of my program, there are two similar methods, they may at the same time, the cause of the deadlock is this?
+ (NSArray*)getChat{
NSManagedObjectContext * managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSError * error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Chat" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"lastMessage" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil];
[request setSortDescriptors:sortDescriptors];
NSArray * FetchResults = [[managedObjectContext executeFetchRequest:request error:&error] copy];
return FetchResults;
}
Managed objects themselves are not thread safe. If multiple threads access the NSManagedObjectContext this will cause a deadlock. Apple recommends on "Concurrency with Core Data" to use the thread confinement pattern for work with concurrency in Core Data. Depending on your app, you can try:
Create a separate managed object context for each thread and share a single persistent store coordinator.
Or create a separate managed object context and persistent store coordinator for each thread.
And with multiple contexts you can pass objects between contexts by passing their objectIDs and fetching them in the other context.
You may want a more sophisticated approach using Nested Contexts. Here is a good article to help you with: Multi-Context CoreData.
I am trying to load items from CoreData into a UITableView. The initial way I did it was to simply grab all the objects from my BankInfo entity, stuff them into an array, and then use the array to populate the UITableViewCells:
- (NSMutableArray *) bankInfos
{
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"BankInfo" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
NSMutableArray *bankInfos = (NSMutableArray*)[context executeFetchRequest:fetchRequest error:&error];
return bankInfos;
}
I'd heard that NSFetchedResultsController could improve performance / memory management so I tried it out (basically implemented it the way Ray Wenderlich tutorial recommended):
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"FailedBankInfo" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"details.closeDate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext sectionNameKeyPath:nil
cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
What I'm finding after using instruments to profile the code is that the NSFetchedResultsController is taking about twice as long to load the objects into the UITableView as my initial method was. This line in particular:
BankInfo *bankInfo = [_fetchedResultsController objectAtIndexPath:indexPath];
is taking 292 ms whereas loading the entire array of BankInfos is taking about 150 ms. Anyone know why this is?
The problem I was having didn't have to do with CoreData performance, but had to do with the fact that I was accidentally saving / loading full size images as thumbnails in the tableview. Once I fixed this, the performance issues went away.
Well, we are talking about ms, it is still quite fast.
The fetched results controller is doing a query to sqllite for each cell. You can turn on sqllite debug in xcode: -com.apple.CoreData.SQLDebug 1 and see for yourself.
The NSArray is populated, stored, and fetched entirely in memory.
The choice between an array and fetched controller is not to be done by taking 'speed' into account.
Basically, if you have a small array of objects, immutable while on screen, then you can safely choose NSArray as table datasource.
Instead, if you have lot of objects or planning to have a growing numbers of objects, that also need to be refreshed often, NSFetchedResultsController is the preferred choice.
I am trying to get the values I have saved in one of my core data objects, however I keep getting this error
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Man''
The resulted error is occurring from the code I have written that tries to access the core data object then logg its content, as show shown below.
if ([manufDBVNumber isEqualToNumber:currentDBVersion]) {
// READ FROM CORE DATA
// WRITE TO CORE DATA
NSManagedObjectContext *context = [self managedObjectContext];
NSLog(#"%#", context);
// Test listing all FailedBankInfos from the store
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Man" inManagedObjectContext:self.managedObjectContext]; // This is where the error is happening.
[fetchRequest setEntity:entity];
NSError *error;
NSMutableArray *manufacturerDictionaryArray = [[NSMutableArray alloc] init];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (Manuf *manuf in fetchedObjects) {
NSLog(#"MANA: %#", man.mana);
NSLog(#"SURGE: %#", man.surge);
NSLog(#"HEALTH: %#", manuf.health);
etc//....
This is how I have synthesized the managedObjectContext and fetchedResultsController
// Core-Data variables used for fetching and managing the object
#synthesize fetchedResultsController = __fetchedResultsController;
#synthesize managedObjectContext = __managedObjectContext;
Any help would be greatly appreciated.
You do this:
NSManagedObjectContext *context = [self managedObjectContext];
But then you access this:
self.managedObjectContext
Assuming your NSLog(#"%#", context); shows a valid NSManagedObjectContext, then I would do this:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Man" inManagedObjectContext:context];
Or, change your original declaration to:
self.managedObjectContext = [self managedObjectContext];
In your viewController.m implementation file, right under this bit of code:
- (void)viewDidLoad
{
add this bit of code:
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
I am using Core Data for my ios app and I am wondering how would I go about in retrieving an entire column from an entity table? For example I am soly interested in grabbing the primary key from my table.
In sql i would just do Select name from MYTABLE.
I think you could do it this way :
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"--table--" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:nil];
NSMutableArray *elementsFromColumn = [[NSMutableArray alloc] init];
for (NSManagedObject *fetchedObject in fetchedObjects) {
[elementsFromColumn addObject:[fetchedObject valueForKey:#"--column--"]];
}
So you have all the elements from a specific column of your table.
Hope it's what you're looking for :)
Look at the documentation for NSFetchRequest. You can ask it to return dictionaries containing specific properties only - this is about as close as you will get. The methods of interest are setResultType: and setPropertiesToFetch:.
I want to get data from multiple rows in coredata into a multidimensional array so I can loop through them to create events in a calendar. However, it doesn't seem possible or advisable from an objects standpoint to have a true multidimensional array, so I've created one NSMutableArray per column of data I want to use for the event attributes (title, note, time of day).
But how do I assign all the values for each of the columns into its own NSMutableArray? Or should I use a NSDictionary to hold the values?
Here's my fetch from CoreData which is pretty standard:
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"My_List"
inManagedObjectContext:context];
[fetchRequest setEntity:entityDescription];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"my_list_name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:20];
[sortDescriptors release];
[sortDescriptor release];
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:#"my_list.cache"];
fetchedResultsController.delegate = self;
NSError *error;
BOOL success = [fetchedResultsController performFetch:&error];
if (!success) {
//Handle the error
}
self.resultsController = fetchedResultsController;
NSArray *fetchedObjects = [fetchedResultsController fetchedObjects];
Here I'm going speculate that I should loop through my NSManagedObject for each of the arrays but I'm not sure how.
for (NSManagedObject *list in context)
{
[ reminderTitleMutableArray addObject:my_list_List.my_list_name ];
[ reminderTitleMutableArray addObject:my_list_List.my_list_description ];
[ reminderTitleMutableArray addObject:my_list_List.my_list_tminus ];
}
Is this the right way?
Thanks
I strongly advise to not pursue this design pattern. By creating multiple or multidimensional arrays, you are cluttering your memory with data that is anyway stored in the core data persistent store. Memory problems are probable.
It would be much better to use some kind of datasource scheme, which I am sure you know from UITableViews, and retrieve the data for each date in your calendar as you need it. With a fetchedResultsController this is quite easy to achieve with NSIndexPaths or some other scheme suitable for your calendar.