I have a simple view which has been successfully loading a table of data from CoreData for the last 18 months. It even works now on devices that have been upgraded to IOS 7. But when I upgraded to Xcode5 and run through the IOS7 3.5inch retina simulator my table is always empty. I have pasted my code below and I can confirm that the fetchRequests are returning the data because I can see this in the NSLog outputs. But why has be table stopped populating the cells?
I feel really stupid because I just cannot figure this one out…
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"listData count in numberOFRowsInSection is: %i", listData.count);
return [self.listData count];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Sessions *info = [_fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"info content is: %#", info.sport);
//Format cell data ready to be displayed
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EE, dd LLL yyyy"];
NSString *dateString = [dateFormat stringFromDate:info.date];
NSNumber *dist1Nbr = info.dist1;
int dist1Int = [dist1Nbr integerValue];
float distIntKorM = ([dist1Nbr integerValue])/1000;
NSString *dist1StrMeters = [[NSString alloc] initWithFormat:#"%i", dist1Int];
NSString *dist1StrKorM = [[NSString alloc] initWithFormat:#"%.01f", distIntKorM];
//Select image to display
if ([info.sport isEqualToString:#"Run"]) {
UIImage *image = [UIImage imageNamed:#"trainers-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
NSLog(#"Cell text for Runs shoudl be: %#", cell.textLabel.text);
} else if ([info.sport isEqualToString:#"Other"]) {
UIImage *image = [UIImage imageNamed:#"weights-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
} else if ([info.sport isEqualToString:#"Swim"]) {
UIImage *image = [UIImage imageNamed:#"goggles-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#m", info.sessiontype, dist1StrMeters];
NSLog(#"Cell text for Swims shoudl be: %#", cell.textLabel.text);
} else if ([info.sport isEqualToString:#"Cycle"]) {
UIImage *image = [UIImage imageNamed:#"bike-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
} else if ([info.sport isEqualToString:#"Brick"]) {
UIImage *image = [UIImage imageNamed:#"brick-15x10.png"];
cell.imageView.image = image;
cell.textLabel.text = [[NSString alloc] initWithFormat:#"%#: (%#),", dateString, info.sport];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Type: %#, Dist: %#", info.sessiontype, dist1StrKorM];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"editSession";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// this cell backgrond colour alternating works!
UIView *bgColor = [cell viewWithTag:100];
if (!bgColor) {
CGRect frame = CGRectMake(0, 0, 320, 50);
bgColor = [[UIView alloc] initWithFrame:frame];
bgColor.tag = 100;
[cell addSubview:bgColor];
[cell sendSubviewToBack:bgColor];
}
if (indexPath.row % 2 == 0) {
bgColor.backgroundColor = [UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1.0];
} else {
bgColor.backgroundColor = [UIColor clearColor]; }
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
if (_context == nil)
{
_context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", _context);
}
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1);
} else {
NSLog(#"After fetchedResultsController: %#", _fetchedResultsController);
//NSLog(#"After managedObjectContext: %#", _fetchedResultsController);
}
self.title = #"Sessions";
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[self setListData:nil];
[self setSelectedSession:nil];
[self setSessionSport:nil];
//[self setRecordCount:nil];
[self setFetchedResultsController:nil];
[self setContext:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
SGK_T4T_01AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDiscription = [NSEntityDescription entityForName:#"Sessions" inManagedObjectContext:context];
//NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"refid" ascending:YES];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDiscription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
NSLog(#"The fetch request returned an array == nil");
} else {
NSLog(#"The fetch request returned an array!!!");
NSLog(#"objects contents is: %#", objects);
NSLog(#"objects count = %i", [objects count]);
listData = objects;
NSLog(#"listData count = %i", [listData count]);
//NSUInteger *recordCount = [objects count];
recordCount = [objects count];
}
//reload tableView:dataSource from CoreData when view reappears...
if (_context == nil)
{
_context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", _context);
}
NSError *error1;
if (![[self fetchedResultsController] performFetch:&error1]) {
NSLog(#"Unresolved error %#, %#", error1, [error1 userInfo]);
exit(-1);
} else {
NSLog(#"viewWillAppear: fetchedResultsController: %#", _fetchedResultsController);
}
//end of reload tableView:dataSource from CoreData when view reappears...
[self.tableView reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//[self setFetchedResultsController:nil];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
//[self setFetchedResultsController:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[_context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![_context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
[self.tableView reloadData];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
if (type == NSFetchedResultsChangeDelete) {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSUInteger index = indexPath.row;
//NSLog(#" Prep4Seg indexPath.row = %u", index);
//NSLog(#" Prep4Seg recordCount = %u", recordCount);
/*
Subtract the row index from the row count to get the correct position in the Array (because I am sorting on date order so tableCell position 0 is position 2 in the Array (if there are 3 only items in the table and array) so if you don't invert the indexPath you end up passing the last item instead of the first or second last item instead of the second and so on...
*/
NSUInteger arrayIndex = (recordCount-index-1);
//NSLog(#" Prep4Seg arrayIndex = %u", arrayIndex);
selectedSession = [listData objectAtIndex:arrayIndex];
//NSLog(#"listData = %#", listData);
//NSLog(#"SelectedSession = %#", selectedSession);
NSNumber *refId = [selectedSession valueForKey:#"refid"];
NSString *refIdToSend = [[NSString alloc] initWithFormat:#"%#", refId];
NSLog(#"Prep4Seg in tableView: refIdToSend = %#", refIdToSend);
if ([segue.identifier isEqualToString:#"editSession"]) {
SGK_T4T_EditSessionDetail *editSessionDetail = segue.destinationViewController;
editSessionDetail.delegate = (id)self;
editSessionDetail.returnFromDatePickerView = [[NSString alloc] initWithFormat:#"no"];
editSessionDetail.recedIndex = refIdToSend;
}
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
And my log output is:
2013-11-09 16:04:04.034 trainForTri copy[6509:a0b] After managedObjectContext: <NSManagedObjectContext: 0xb589bc0>
2013-11-09 16:04:04.036 trainForTri copy[6509:a0b] After fetchedResultsController: <NSFetchedResultsController: 0xb5e2c40>
2013-11-09 16:04:04.040 trainForTri copy[6509:a0b] The fetch request returned an array!!!
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects contents is: (
"<NSManagedObject: 0xb5c8570> (entity: Sessions; id: 0xb5ac970 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p1> ; data: <fault>)",
"<NSManagedObject: 0xb5d6320> (entity: Sessions; id: 0xb58a2a0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p2> ; data: <fault>)",
"<NSManagedObject: 0xb5d0370> (entity: Sessions; id: 0xb5dc270 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p3> ; data: <fault>)",
"<NSManagedObject: 0xb5e3dd0> (entity: Sessions; id: 0xb5ebcc0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p4> ; data: <fault>)",
"<NSManagedObject: 0xb585e40> (entity: Sessions; id: 0xb5e4e40 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p5> ; data: <fault>)"
)
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects count = 5
2013-11-09 16:04:04.042 trainForTri copy[6509:a0b] listData count = 5
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] viewWillAppear: fetchedResultsController: <NSFetchedResultsController: 0xb5a01e0>
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] listData count in numberOFRowsInSection is: 5
OK, found the issue with this. Eventually after almost wanting to throw my Macbook out of the window in frustration with Xcode5 I shut everything down and restarted. when I opened Xcode, built and ran my App it lo longer loaded an empty table - it now produced an error which indicated that there was something wrong with my NSFetchedResultsController. I traced it to an issue with the cache not clearing (or not being mutable) - so I removed the cache name and set it to nil and everything is working again. I am not sure if this is an IOS7/Xcode5 issue but it has not been a problem until this upgrade. For anyone searching for a similar fix here is the offending line of code:
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:#"Root"];
And this is the version that works!
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:nil];
I hope I'm not the only one ever to struggle with this and therefore just a thickie!
Related
The UITableViewController freezes when scrolling or when viewDidAppear:. I see that when the problem starts, the app start to allocate objects uncontrollably.
I have the following project for iOS: basically download information from CoreData, but when I go to display the data in the table, the application freezes (both the device and the simulator). But if I show the arrangement in a downloaded NSLog no errors. The code is as follows:
I see that when the problem starts, the app start to allocate objects uncontrollably.
The UITableViewController freezes when scrolling or when viewDidAppear:
TableViewController.h
#interface Set_ScheduleViewController : UITableViewController
{
STCore *core;
UILabel *label;
NSArray *objects;
}
#end
TableViewController.m:
#implementation Set_ScheduleViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
core = [[STCore alloc] init];
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)reloadData
{
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
objects = [core getAllClassesUsingSortDescriptions:#[sort]];
[[self tableView] reloadData];
}
- (void)viewDidAppear:(BOOL)animated
{
[self reloadData];
[super viewDidAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [objects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 120, 20)];
label.textColor = [UIColor colorWithHex:0x88B6DB];
label.font = [UIFont systemFontOfSize:12.0f];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentRight;
label.minimumFontSize = 12.0f;
tableView.separatorColor = [UIColor colorWithHex:0xDAE1E6];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor colorWithHex:0x393B40];
cell.textLabel.font = [UIFont boldSystemFontOfSize:16.0f];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.textColor = [UIColor colorWithHex:0x393B40];
cell.detailTextLabel.font = [UIFont systemFontOfSize:12.0f];
}
cell.textLabel.text = [[objects objectAtIndex:indexPath.row] name];
cell.detailTextLabel.text = [[objects objectAtIndex:indexPath.row] location];
STMultipleDate *dates = [STMultipleDate new];
for (Schedule *sch in [[objects objectAtIndex:indexPath.row] schedule]) {
STDate *date = [STDate new];
[date setWeekday:[[sch day] integerValue]];
[date setHour:[[sch hour] integerValue]];
[date setMinutes:[[sch minutes] integerValue]];
[dates addDate:date];
}
label.text = [STCore splitDates:dates];
cell.accessoryView = label;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
if ([objects count] < 1) {
return NSLocalizedString(#"SETSCH_FOOTER_DEFAULT_404", #"");
}
return nil;
}
STCore.m
- (NSArray *)getAllClassesUsingSortDescriptions:(NSArray *)descs
{
if (![self isReady]) {
return #[];
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Classes" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];
[fetchRequest setSortDescriptors:descs];
NSError *error;
NSArray *returned = [_context executeFetchRequest:fetchRequest error:&error];
if (error) {
[_delegate core:self didRecivedAnError:error];
}
return returned;
}
In your viewDidLoad you're locking the context with [[core context] lock];, which is causing your getAllClassesUsingSortDescriptions to wait for the lock to clear. Remove the lock.
I have some "details" saved into my Core Data, and I'm trying to call it out from an NSFetchedResultsController into my tableView. For whatever reason, the tableView isn't populating once the block is finished running.
I have been searching and asking everywhere I can to try and figure out this whole Core Data debacle. Hopefully, someone on here is kind enough to help me out!
HomeViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"Home";
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0 green:0.7 blue:2.3 alpha:1];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:#selector(addShindy:)];
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"light_alu.png"]];
self.tableView.opaque = NO;
self.tableView.backgroundView = nil;
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(refresh:)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
[self setShindyDatabase:self.shindyDatabase];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.shindyDatabase) {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
self.shindyDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
}
}
- (void)refresh:(UIRefreshControl *)sender
{
[self useDocument];
[sender endRefreshing];
}
- (void)addShindy:(UIBarButtonItem *)sender
{
AddShindyViewController *addShindyViewController = [[AddShindyViewController alloc] initWithNibName:#"AddShindyViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addShindyViewController];
[self presentViewController:navController animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma Core Date Stack
- (void)fetchShindyDataIntoDocument:(UIManagedDocument *)document
{
dispatch_queue_t fetchIntoDocument = dispatch_queue_create("Fetch Into Document", nil);
dispatch_async(fetchIntoDocument, ^{
NSArray *shindys = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
for (NSDictionary *shindyInfo in shindys) {
[Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:document.managedObjectContext];
}
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
});
}
- (void)setShindyDatabase:(UIManagedDocument *)shindyDatabase
{
if (_shindyDatabase != shindyDatabase) {
_shindyDatabase = shindyDatabase;
[self useDocument];
}
}
- (void)useDocument
{
NSError *error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.shindyDatabase.fileURL path]]) {
NSLog(#"Create document");
[self.shindyDatabase saveToURL:self.shindyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
[self fetchShindyDataIntoDocument:self.shindyDatabase];
if (!success) {
NSLog(#"error for creation of document: %#", [error localizedDescription]);
}
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateClosed) {
NSLog(#"Closed document");
[self.shindyDatabase.managedObjectContext.parentContext performBlock:^{
[self setupFetchedResultsController];
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateNormal) {
NSLog(#"Normal Document");
[self setupFetchedResultsController];
}
if (error) {
NSLog(#"Error in useDocument: %#", [error localizedDescription]);
}
}
- (void)setupFetchedResultsController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
// request.predicate = [NSPredicate predicateWithFormat:#"details = %#", [self.shindyDatabase valueForKey:#"details"]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.shindyDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
#pragma mark - Table view data source
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 75;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
Shindy *shindy = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"%#", shindy.details);
cell.textLabel.text = shindy.details;
Shindy+CreateDB.m
+ (Shindy *)shindyWithShindyDBInfo:(NSDictionary *)shindyInfo
inManagedObjectContext:(NSManagedObjectContext *)context
{
Shindy *shindy = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
// NSSortDescriptor *dateAndTimeSort = [NSSortDescriptor sortDescriptorWithKey:#"dateAndTime" ascending:YES];
NSSortDescriptor *detailsSort = [NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES];
// NSSortDescriptor *locationSort = [NSSortDescriptor sortDescriptorWithKey:#"location" ascending:YES];
// NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
// NSSortDescriptor *photoSort = [NSSortDescriptor sortDescriptorWithKey:#"photo" ascending:YES];
// NSSortDescriptor *timePostedSort = [NSSortDescriptor sortDescriptorWithKey:#"timePosted" ascending:YES];
// title
request.sortDescriptors = [NSArray arrayWithObject:detailsSort];
// request.sortDescriptors = [NSArray arrayWithObjects:dateAndTimeSort, detailsSort, locationSort, nameSort, photoSort, timePostedSort, nil];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if (error) {
NSLog(#"document failed in file: %#", [error localizedDescription]);
}
if (!matches || ([matches count] > 1)) {
NSError *error = nil;
NSLog(#"error in DBInfo: %#", [error localizedDescription]);
} else if ([matches count] == 0) {
shindy = [NSEntityDescription insertNewObjectForEntityForName:#"Shindy" inManagedObjectContext:context];
// shindy.dateAndTime = [shindyInfo objectForKey:#"dateAndTime"];
shindy.details = [shindyInfo objectForKey:#"details"];
// shindy.location = [shindyInfo objectForKey:#"location"];
// shindy.name = [shindyInfo objectForKey:#"name"];
// shindy.photo = [shindyInfo objectForKey:#"photo"];
// shindy.timePosted = [shindyInfo objectForKey:#"timePosted"];
// title
// Guestlist? The rest?
// Use below for reference
// shindy.whoseShindy = [User userWithName:[shindyInfo objectForKey:#"whoseShindy"] inManagedObjectContext:context];
} else {
shindy = [matches lastObject];
}
return shindy;
}
EDIT:
I suppose I should have also shown a file of which I have set as a subclass of my HomeViewController. It's basically the same thing as the code that is given to you to paste in the Apple Documentation
CoreDataTableViewController.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface CoreDataTableViewController : UITableViewController <NSFetchedResultsControllerDelegate>
#property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
- (void)performFetch;
#property (nonatomic) BOOL suspendAutomaticTrackingOfChangesInManagedObjectContext;
#property BOOL debug;
#end
CoreDataTableViewController.m
#interface CoreDataTableViewController()
#property (nonatomic) BOOL beganUpdates;
#end
#implementation CoreDataTableViewController
#pragma mark - Properties
#synthesize fetchedResultsController = _fetchedResultsController;
#synthesize suspendAutomaticTrackingOfChangesInManagedObjectContext = _suspendAutomaticTrackingOfChangesInManagedObjectContext;
#synthesize debug = _debug;
#synthesize beganUpdates = _beganUpdates;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark - Fetching
- (void)performFetch
{
if (self.fetchedResultsController) {
if (self.fetchedResultsController.fetchRequest.predicate) {
if (self.debug) NSLog(#"[%# %#] fetching %# with predicate: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate);
} else {
if (self.debug) NSLog(#"[%# %#] fetching all %# (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName);
}
NSError *error;
[self.fetchedResultsController performFetch:&error];
if (error) NSLog(#"[%# %#] %# (%#)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]);
} else {
if (self.debug) NSLog(#"[%# %#] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
}
[self.tableView reloadData];
}
- (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc
{
NSFetchedResultsController *oldfrc = _fetchedResultsController;
if (newfrc != oldfrc) {
_fetchedResultsController = newfrc;
newfrc.delegate = self;
if ((!self.title || [self.title isEqualToString:oldfrc.fetchRequest.entity.name]) && (!self.navigationController || !self.navigationItem.title)) {
self.title = newfrc.fetchRequest.entity.name;
}
if (newfrc) {
if (self.debug) NSLog(#"[%# %#] %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), oldfrc ? #"updated" : #"set");
[self performFetch];
} else {
if (self.debug) NSLog(#"[%# %#] reset to nil", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
[self.tableView reloadData];
}
}
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[[self.fetchedResultsController sections] objectAtIndex:section] name];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [self.fetchedResultsController sectionIndexTitles];
}
#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) {
[self.tableView beginUpdates];
self.beganUpdates = YES;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if (self.beganUpdates) [self.tableView endUpdates];
}
- (void)endSuspensionOfUpdatesDueToContextChanges
{
_suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
}
- (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend
{
if (suspend) {
_suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
} else {
[self performSelector:#selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0];
}
}
#end
And then last, but not least, I have the header file for my HomeViewController of which I implement CoreDataTableViewController. Hopefully this is useful in better explaining what I've got.
HomeViewController.h
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#import "CoreDataTableViewController.h"
#interface HomeViewController : CoreDataTableViewController
#property (strong, nonatomic) UIManagedDocument *shindyDatabase;
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
#end
It's quite difficult to see what is going on, but, I think you need to do the following steps when the block has finished (I suppose this since I don't see any similar in your code).
execute the fetch request through the fetched controller
reload the data table
So,
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
// error handling here...
}
[yourTable reloadData];
Try and let me know. If doesn't work, try to edit a minimal question because there is too much code to follow.
Hope that helps.
I ended up figuring this, and many other Core Data issues I was having. I wasn't setting my managed object context to a store!! DUH!!!
self.managedObjectContext = [(AppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];
That did the trick. Everything began working after that.
I hope this is able to point out another duh to anybody out there forgetting the same thing I did!
I had my app navigating views perfectly. Now, for some reason that I can't figure out, my detailView is not presenting on the pushViewController:detail method in my modal view.
I cannot figure out why it's not working any more. Any help would be appreciated. Thanks.
Here's the method:
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
Here's the class code. I'm not sure if I need to pass in a navigationController with modalView:
//
// ModalView.m
// DiningLog
//
// Created by Eric Rea on 10/10/11.
// Copyright 2011 Avid. All rights reserved.
//
#import "ModalView.h"
#import "DetailView.h"
#implementation ModalView
#synthesize tableView, excersizeName, numSets, time, restTime, dateFormatter, rating, excersizeArray, plistArray, numberWithBool;
-(IBAction) cancel:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
-(IBAction) save:(id)sender{
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"ExcersizeList.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"Excersizes" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property list into dictionary object
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp)
{
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
// assign values
self.plistArray = [NSMutableArray arrayWithArray:[temp objectForKey:#"Excersizes"]];
NSLog(#"The contents of plistArray is%#", plistArray);
// set the variables to the values in the text fields
self.excersizeArray = [[NSMutableArray alloc] initWithCapacity:4];
[excersizeArray addObject:excersizeName];
[excersizeArray addObject:numSets];
[excersizeArray addObject:time];
[excersizeArray addObject:restTime];
[plistArray addObject:excersizeArray];
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: plistArray, nil] forKeys:[NSArray arrayWithObjects: #"Excersizes", nil]];
NSString *error = nil;
// create NSData from dictionary
// NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
// check is plistData exists
if(plistDict)
{
// write plistData to our Data.plist file
[plistDict writeToFile:plistPath atomically:YES];
}
else
{
NSLog(#"Error in saveData: %#", error);
[error release];
}
[self dismissModalViewControllerAnimated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tView {
// Return the number of sections.
return 1;
}
-(void)setObject:(id)object forNum:(int)num{
if(num == 0){
self.excersizeName = object;
NSLog(#"res %#", self.excersizeName);
}else if(num == 1){
self.numSets = object;
NSLog(#"res %#", self.numSets);
}else if(num == 2){
self.time = object;
NSLog(#"res %#", self.time);
}else if(num == 3){
self.restTime = object;
NSLog(#"res %#", self.restTime);
}else if(num == 4){
self.rating = [object floatValue];
}
[tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 5;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
}
if(indexPath.row == 0){
cell.textLabel.text = #"Excersize";
cell.detailTextLabel.text = excersizeName;
}
if(indexPath.row == 1){
cell.textLabel.text = #"Sets";
cell.detailTextLabel.text = numSets;
}
if(indexPath.row == 2){
cell.textLabel.text = #"Time";
cell.detailTextLabel.text = time;
}
if(indexPath.row == 3){
cell.textLabel.text = #"Rest";
cell.detailTextLabel.text = restTime;
}
if(indexPath.row == 4){
cell.textLabel.text = #"Rating";
cell.detailTextLabel.text = [NSString stringWithFormat:#"%f",rating];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (NSDateFormatter *)dateFormatter {
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
}
return dateFormatter;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 1){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 2){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 3){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
if(indexPath.row == 4){
NSLog(#"hey");
DetailView * detail = [[DetailView alloc] initWithNumber:indexPath.row];
detail.delegate = self;
[[self navigationController] pushViewController:detail animated:YES];
}
}
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Have you debugged and checked that your navigationController isn't nil ?
I figured it out. I accidentally erased the method insertNewObject in my rootViewController. When I rewrote it, I forgot to add in ModalView * modal = [[ModalView alloc] init];. That was the problem.
Here's what the method looks like now that it's working:
- (void)insertNewObject {
ModalView * modal = [[ModalView alloc] init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:modal];
[self presentModalViewController:controller animated:YES];
}
I am getting a crash at line [selectedSession release]; in dealloc:
Default [NSCheapMutableString release]: message sent to deallocated instance
I don't understand why isn't this normal to put in dealloc?
All current code below:
LogViewController
#implementation LogViewController
#synthesize fetchedResultsController = __fetchedResultsController;
#synthesize managedObjectContext;
#synthesize logArray;
#synthesize logTableView;
#synthesize imageView;
#synthesize session;
#synthesize selectedSession;
- (void)dealloc
{
[logArray release];
[logTableView release];
[session release];
[__fetchedResultsController release];
[managedObjectContext release];
[imageView release];
[selectedSession release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
self.logTableView.rowHeight = 47;
[super viewDidLoad];
self.navigationItem.title = #"Log";
logTableView.backgroundColor = [UIColor clearColor];
logTableView.separatorColor = [UIColor grayColor];
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:24/255.0 green:83/255.0 blue:170/255.0 alpha:1.0];
self.logArray = [[NSArray alloc]initWithObjects:#"Today", #"Previous", #"Past Week", #"Past Month", #"All Workouts", nil];
if (managedObjectContext == nil)
{
self.managedObjectContext = [(CurlAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
}
- (void)viewDidUnload
{
self.logTableView = nil;
self.fetchedResultsController = nil;
self.imageView = nil;
self.managedObjectContext = nil;
[super viewDidUnload];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.logArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TDBadgedCell *cell = [[[TDBadgedCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(TDBadgedCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
cell.textLabel.textColor = [UIColor blackColor];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [logArray objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor clearColor];
cell.imageView.image = [UIImage imageNamed:#"17-bar-chart.png"];
UIImageView *myImageView = nil;
myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"silvercell5.png"]];
[cell setBackgroundView:myImageView];
[myImageView release];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMM d, y"];
NSDate *date = nil;
if (indexPath.row == 0)
{
date = [NSDate date];
NSString *dateString = [dateFormatter stringFromDate:date];
cell.badgeString = dateString;
}
else if (indexPath.row == 1)
{
if ([[self.fetchedResultsController fetchedObjects]count] > 1)
{
self.session = [[self.fetchedResultsController fetchedObjects]objectAtIndex:1];
NSDate *date = self.session.timeStamp;
NSString *dateString = [dateFormatter stringFromDate:date];
cell.badgeString = dateString;
}
else
{
cell.badgeString = #"None";
}
}
else if (indexPath.row > 1)
{
cell.badgeString = [NSString stringWithFormat:#"%i", [[self.fetchedResultsController fetchedObjects]count]];
}
cell.badgeColor = [UIColor colorWithRed:24/255.0 green:83/255.0 blue:170/255.0 alpha:1.0];
[dateFormatter release];
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.row == 0 || indexPath.row == 1)
{
SessionViewController *detailViewController = [[SessionViewController alloc] initWithNibName:#"SessionViewController" bundle:nil];
detailViewController.title = [logArray objectAtIndex: indexPath.row];
self.selectedSession = (Session *)[__fetchedResultsController objectAtIndexPath:indexPath];
detailViewController.selectedSession = self.selectedSession;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMM d, y"];
NSString *dateString = [dateFormatter stringFromDate:selectedSession.timeStamp];
detailViewController.title = dateString;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
[dateFormatter release];
}
else
{
LogResultsViewController *detailViewController = [[LogResultsViewController alloc] initWithNibName:#"LogResultsTableViewController" bundle:nil];
detailViewController.title = [logArray objectAtIndex: indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
}
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Session" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0] ;
NSDate *today = [NSDate date];
NSDate *thisWeek = [today dateByAddingTimeInterval: -604800.0];
NSDate *thisMonth = [today dateByAddingTimeInterval: -2629743.83]; // Use NSCalendar for
if (indexPath.row ==2)
{
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"(date >= %#) AND (date <= %#)", thisWeek, today]];
}
else if (indexPath.row ==3)
{
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"(date >= %#) AND (date <= %#)", thisMonth, today]];
}
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"timeStamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
NSLog(#"Number of Objects = %i",
[[fetchedResultsController fetchedObjects] count]);
return fetchedResultsController;
NSLog(#"Number of Objects = %i",
[[fetchedResultsController fetchedObjects] count]);
}
#pragma mark - Fetched results controller delegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.logTableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.logTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.logTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.logTableView;
switch(type)
{
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.logTableView endUpdates];
}
LogResultsViewController
#implementation LogResultsViewController
#synthesize fetchedResultsController = __fetchedResultsController;
#synthesize managedObjectContext;
#synthesize resultsTableView;
#synthesize selectedSession;
- (void)dealloc
{
[__fetchedResultsController release];
[managedObjectContext release];
[selectedSession release];
[resultsTableView release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.resultsTableView.separatorColor = [UIColor grayColor];
self.resultsTableView.rowHeight = 50;
[self managedObjectContext];
}
- (NSManagedObjectContext *)managedObjectContext
{
if (managedObjectContext != nil)
{
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [(CurlAppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator];
if (coordinator != nil)
{
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext;
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.managedObjectContext = nil;
self.fetchedResultsController = nil;
self.resultsTableView = nil;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Session *session = (Session *)[__fetchedResultsController objectAtIndexPath:indexPath];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"eeee, MMM d, y"];
NSString *dateString = [dateFormatter stringFromDate:session.timeStamp];
NSDate *lastDate = session.timeStamp;
NSDate *todaysDate = [NSDate date];
NSTimeInterval lastDiff = [lastDate timeIntervalSinceNow];
NSTimeInterval todaysDiff = [todaysDate timeIntervalSinceNow];
NSTimeInterval dateDiff = todaysDiff-lastDiff;
NSTimeInterval dayDifference = dateDiff/86400;
int days = (int) dayDifference;
NSLog(#"%i days",days);
cell.textLabel.text = dateString;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.detailTextLabel.text = [NSString stringWithFormat: #"%i days ago", days];
cell.detailTextLabel.textColor = [UIColor colorWithRed:24/255.0 green:83/255.0 blue:170/255.0 alpha:1.0];
cell.imageView.image = [UIImage imageNamed:#"11-clock.png"];
self.resultsTableView.tableFooterView = [[[UIView alloc] init] autorelease];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"silvercell3.png"]];
[cell setBackgroundView:myImageView];
[dateFormatter release];
[myImageView release];
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the managed object for the given index path
NSManagedObjectContext *context = [__fetchedResultsController managedObjectContext];
[context deleteObject:[__fetchedResultsController objectAtIndexPath:indexPath]];
// Commit the change.
NSError *error = nil;
// Update the array and table view.
if (![managedObjectContext save:&error])
{
// Handle the error.
}
//[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
}
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SessionViewController *sessionViewController = [[SessionViewController alloc] initWithNibName:#"SessionViewController" bundle:nil];
selectedSession = (Session *)[__fetchedResultsController objectAtIndexPath:indexPath];
sessionViewController.selectedSession = self.selectedSession;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMM d, y"];
NSString *dateString = [dateFormatter stringFromDate:selectedSession.timeStamp];
sessionViewController.title = dateString;
[self.navigationController pushViewController:sessionViewController animated:YES];
[sessionViewController release];
[dateFormatter release];
}
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Session" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"timeStamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![fetchedResultsController performFetch:&error])
{
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return fetchedResultsController;
}
#pragma mark - Fetched results controller delegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.resultsTableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.resultsTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.resultsTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.resultsTableView;
switch(type)
{
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.resultsTableView endUpdates];
}
SessionViewController
#implementation SessionViewController
#synthesize exerciseArray;
#synthesize selectedSession;
- (void)dealloc
{
[exerciseArray release];
[selectedSession release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(IBAction)showActionSheet {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Share" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Twitter",#"Facebook",nil];
[actionSheet showInView:self.tabBarController.view];
[actionSheet release];
}
- (void)tweet
{
SHKItem *aTweet = [SHKItem text:[NSString stringWithFormat: #"Twitter: testing 1,2,3."]];
[SHKTwitter shareItem:aTweet];
}
- (void)facebook
{
SHKItem *post = [SHKItem text: [NSString stringWithFormat: #"Facebook: testing 1,2,3."]];
// post.URL = [NSURL URLWithString:#"http://sugarrush-app.com/"];
[SHKFacebook shareItem:post];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *actionButton = [[UIBarButtonItem alloc] initWithTitle:#"Share" style:UIBarButtonItemStylePlain target:self action:#selector(showActionSheet)];
self.navigationItem.rightBarButtonItem = actionButton;
[actionButton release];
NSSet *exercises = [self.selectedSession valueForKey:#"exercises"];
NSArray *sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"timeStamp" ascending:YES]];
NSArray *sorted = [exercises sortedArrayUsingDescriptors:sortDescriptors];
self.exerciseArray = sorted;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [exerciseArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
Exercise *exercise = (Exercise *)[exerciseArray objectAtIndex:indexPath.row];
cell.textLabel.text = exercise.name;
return cell;
}
#end
The only objects you should be releasing or setting to nil in viewDidUnload are like buttons, labels, textBoxes etc.
When you do self.selectedSession = nil, for example, it is calling the release for that method; that is the point of properties, they handle the allocs and releases.
You posted a tableView:didSelectRowAtIndexPath:, but I don't think you told us which class that was in.
In any case, that method seems to have a bug:
selectedSession = (Session *)[__fetchedResultsController objectAtIndexPath:indexPath];
sessionViewController.selectedSession = self.selectedSession;
I think on the first line, you meant to say self.selectedSession, assuming you go on to release selectedSession in this class' dealloc. (This may not be your only issue)
EDIT:
You should set properties to nil in viewDidUnload if and only if those properties were set as a result of the loading of the view from your nib, or were set in loadView, or in viewDidLoad. The reason you're doing this is because viewDidLoad or loadView may be called more than once during the lifetime of the view controller.
EDIT:
Check that you are using the property when setting fetchedResultsController and make sure you aren't setting that to nil on viewDidUnload.
Dont set selectedSession and exerciseArray to nil in viewDidUnload.
Since you're doing that, it will crash in the dealloc as you're trying to release nil objects.
Also, before you release arrays, it's always a good idea to call [array removeAllObjects].
in your viewDidLoad method you are setting self.selectedSession and self.exerciseArray to nil. You should only set interface outlets to nil in viewDidLoad. But this isn't the cause of your crash because by the time you get to dealloc, you are just sending release to nil.
you might want to look into the contents of the selectedSession Object. you might be over releasing an NSString in one of it's members
Over the last few days, I've searched far and wide and followed every resolution I could find online with no success.
Basically, I'm refreshing a Core Data entity from JSON data I pull from the web. I can clear out the previous data pulled from the web and load in the new data. The problem occurs when I attempt to save to Core Data "[self.managedObjectContext save:&error];".
The app just locks up.
The code from my view controller is shown below. I would greatly appreciate any assistance.
** CODE ***
//
// ChargeEntryViewController.m
// pcc
//
// Created by Tim Black on 3/14/11.
// Copyright 2011 Mobile Intents. All rights reserved.
//
#import "ChargeEntryViewController.h"
#import "pccAppDelegate.h"
#import "ChargeEntryPatientViewController.h"
#import "CJSONDeserializer.h"
#interface ChargeEntryViewController (PrivateMethods)
- (NSString *)jsonFromURLString:(NSString *)urlString;
- (void)handleError:(NSError *)error;
#end
#implementation ChargeEntryViewController
#synthesize fetchedResultsController=fetchedResultsController_;
#synthesize managedObjectContext=managedObjectContext_;
#synthesize providerArray;
#synthesize clearBtn;
#synthesize setBtn;
#synthesize patientController;
#pragma mark - Button methods
-(IBAction) clearAll:(id)sender{
selRow = -1;
[providerList reloadData];
}
-(IBAction) setPatientView:(id)sender {
if (self.patientController == nil) {
ChargeEntryPatientViewController *tmpController = [[ChargeEntryPatientViewController alloc] initWithNibName:#"ChargeEntryPatientView" bundle:nil];
self.patientController = tmpController;
[tmpController release];
}
patientController.title = #"Patient Selection";
[self.navigationController pushViewController:patientController animated:YES];
}
/*
Used to refresh the providers list from nrhsportal
*/
-(void)refreshProviders {
NSError *error = nil;
// get provider code from app delegate
pccAppDelegate *appDelegate = (pccAppDelegate *)[[UIApplication sharedApplication] delegate];
// first, clear out current list stored locally
NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease];
[fetch setEntity:[NSEntityDescription entityForName:#"Provider" inManagedObjectContext:self.managedObjectContext]];
NSArray *result = [self.managedObjectContext executeFetchRequest:fetch error:&error];
if (error != nil) {
[self handleError:error];
return;
}
for (id basket in result) {
[self.managedObjectContext deleteObject:basket];
}
// add (My Patients) entry
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:#"Provider" inManagedObjectContext:self.managedObjectContext];
[newManagedObject setValue:#"(My Patients)" forKey:#"fullname"];
[self.managedObjectContext insertObject:newManagedObject];
NSString *code = appDelegate.groupCode;
// create remote source URI
NSString *urlString = [NSString stringWithFormat:#"%s%#%s", "https://nrhsportal.nrh-ok.com/pccdata.svc/GetProviders?groupcode='", code, "'&$format=json"];
NSLog(#"URL String %#", urlString);
// Perform HTTP GET to the REST web service which returns JSON
NSString *jsonString = [self jsonFromURLString:urlString];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF32BigEndianStringEncoding];
// Parse JSON results to convert to a dictionary
CJSONDeserializer *jsonDeserializer = [CJSONDeserializer deserializer];
error = nil;
NSDictionary *resultsDictionary = [jsonDeserializer deserializeAsDictionary:jsonData error:&error];
if (error != nil) {
[self handleError:error];
return;
}
// Traverse through returned dictionary to populate tweets model
NSDictionary *topArray = [resultsDictionary objectForKey:#"d"];
NSArray *resultsArray = [topArray objectForKey:#"results"];
for (NSDictionary *resultDictionary in resultsArray) {
// create the
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:#"Provider" inManagedObjectContext:self.managedObjectContext];
NSString *providerName = [resultDictionary objectForKey:#"fullname"];
[newManagedObject setValue:providerName forKey:#"fullname"];
[self.managedObjectContext insertObject:newManagedObject];
}
error = nil;
[self.managedObjectContext save:&error];
if (error != nil) {
[self handleError:error];
return;
}
[newManagedObject release];
[result release];
}
// This will issue a request to a web service API via HTTP GET to the URL specified by urlString.
// It will return the JSON string returned from the HTTP GET.
- (NSString *)jsonFromURLString:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"GET"];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[request release];
[self handleError:error];
NSString *resultString = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
return [resultString autorelease];
}
// This shows the error to the user in an alert.
- (void)handleError:(NSError *)error {
if (error != nil) {
UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:#"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:#"Close" otherButtonTitles:nil];
[errorAlertView show];
[errorAlertView release];
}
}
#pragma mark - View lifecycle
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
selRow = -1;
// refresh the provider list from remote data
[self refreshProviders];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:#"fullname"] description];
cell.textLabel.font=[UIFont systemFontOfSize:16.0];
if ([cell.textLabel.text isEqualToString: #"(My Patients)"]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// Reflect selection in data model
} else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
// Reflect deselection in data model
}
}
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController_ != nil) {
return fetchedResultsController_;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Provider" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"fullname" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController_;
}
#pragma mark - Memory management
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc
{
[patientController release];
[clearBtn release];
[setBtn release];
[providerArray release];
[fetchedResultsController_ release];
[managedObjectContext_ release];
[super dealloc];
}
#end
You don't need the line
[self.managedObjectContext insertObject:newManagedObject];
since you've already insertNewObjectForEntityForName before with the newManagedObject.