Tableview get index out of bounds with empty array - ios

I have a tableview that is filled with a fetchedresultscontroller and a searchbar. Up until now while creating the app i have only been using 7 cells and have worked great but since i started using more than 7 cells i get the error of out of bounds empty array when i touch the searchbar. but when i return it back to 7 cells it works perfect.
What could possibly be wrong?
Error:
erminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 2 beyond bounds for empty array'
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Exercises";
id appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"%# %#", error, [error userInfo]);
abort();
}
_searchResults = [[NSMutableArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSIndexPath *selectedIndexPath = [_tableView indexPathForSelectedRow];
if (!selectedIndexPath) {
[_tableView setContentOffset:CGPointMake(0, 44) animated:NO];
}
else {
[_tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
}
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if (self.searchDisplayController.isActive) {
[self.searchDisplayController setActive:NO animated:YES];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (self.searchDisplayController.isActive) {
return 1;
}
return [[_fetchedResultsController sections] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (self.searchDisplayController.isActive) {
return nil;
}
return [[[_fetchedResultsController sections] objectAtIndex:section] name];
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 22)];
view.backgroundColor = [UIColor colorWithRed:20.0/255.0 green:20.0/255.0 blue:20.0/255.0 alpha:0.8];
UILabel *sectionLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 160, 22)];
sectionLabel.font = [UIFont fontWithName:#"Avenir-Book" size:16.0f];
sectionLabel.text = #"Search Results";
if (!self.searchDisplayController.isActive) {
sectionLabel.text = [[[_fetchedResultsController sections] objectAtIndex:section] name];
}
sectionLabel.backgroundColor = [UIColor clearColor];
sectionLabel.textColor = [UIColor whiteColor];
[view addSubview:sectionLabel];
return view;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.searchDisplayController.isActive) {
return [_searchResults count];
}
return [[[_fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"exerciseCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
[self stampCell:cell atIndexPath:indexPath];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
#pragma mark - Cell
- (void)stampCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
if ([cell.reuseIdentifier isEqualToString:#"exerciseCell"]) {
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 2, 150, 22)];
textLabel.tag = kExerciseCellTextLabel;
textLabel.font = [UIFont systemFontOfSize:18.0];
textLabel.textColor = [UIColor blackColor];
textLabel.highlightedTextColor = [UIColor whiteColor];
textLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview:textLabel];
UILabel *detailTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 24, 150, 18)];
detailTextLabel.tag = kExerciseCellDetailTextLabel;
detailTextLabel.font = [UIFont systemFontOfSize:14.0];
detailTextLabel.textColor = [UIColor colorWithRed:128.0/255.0 green:128.0/255.0 blue:128.0/255.0 alpha:1.0];
detailTextLabel.highlightedTextColor = [UIColor colorWithRed:127.0/255.0 green:127.0/255.0 blue:127.0/255.0 alpha:1.0];
detailTextLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview:detailTextLabel];
}
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
if ([cell.reuseIdentifier isEqualToString:#"exerciseCell"]) {
UILabel *textLabel = (UILabel *)[cell.contentView viewWithTag:kExerciseCellTextLabel];
UILabel *detailTextLabel = (UILabel *)[cell.contentView viewWithTag:kExerciseCellDetailTextLabel];
Exercise *exercise;
if (self.searchDisplayController.isActive) {
exercise = [_searchResults objectAtIndex:indexPath.row];
}
else {
exercise = [_fetchedResultsController objectAtIndexPath:indexPath];
}
textLabel.text = [exercise valueForKey:kExerciseName];
detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", [[exercise valueForKey:kExerciseEType] valueForKey:kExerciseTypeName], [[exercise valueForKey:kExerciseGear] valueForKey:kGearName]];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"exerciseDetail" sender:self];
}
#pragma mark - UISearchBarDelegate
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[_searchResults removeAllObjects];
if (searchString.length > 0) {
for (Exercise *exercise in [_fetchedResultsController fetchedObjects]) {
NSRange range = [[exercise valueForKey:kExerciseName] rangeOfString:searchString options:NSCaseInsensitiveSearch];
if (range.location == 0) {
[_searchResults addObject:exercise];
}
}
}
return YES;
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar*)searchBar {
[super setPan];
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
[super setPan];
return YES;
}
#pragma mark - NSFetchedResultsControllerDelegate
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kExercise inManagedObjectContext:_managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:kExerciseName ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sort]];
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:_managedObjectContext sectionNameKeyPath:kExerciseFirstLetter cacheName:#"ExerciseList"];
[self setFetchedResultsController:fetchedResultsController];
[_fetchedResultsController setDelegate:self];
return _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[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)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
#end

It shows like some of array remains empty..the better way to check it
-Put NSLog statement after array element and run it..IT shows which array remains empty.
By doing so if your problem doesn't get solved..please let me know..so,i can help you further..

Where do you see the crash - when showing just search results or when showing the entire list?
If its just search results, then your _searchResults does not have more than 7 records.
If it is when you are showing all results, then check the number of records in each value of _fetchedResultsController.sections. Looks like they don't have more than 7 records.

Hi i guess ur removing all elements from _searchResults may be due to this the app is crashing.please check this once.
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[_searchResults removeAllObjects];

Related

UITableView sections are not ordered as expected

I am using a tableView with customised section titles. The core data objects are shown on a precise section depending on the value from a transient attribute called sectionIdentifier. Everything is working as expected, but the order of the sections is not responding as I expected. This should be the sections order:
1. OVERDUE, sectionIdentifier = 0
2. TODAY, sectionIdentifier = 1
3. TOMORROW, sectionIdentifier = 2
4. UPCOMING, sectionIdentifier = 3
5. SOMEDAY, sectionIdentifier = 4
At this app state, the section order is as shown in the image below:
Any help is welcome to explain this behaviour and to find the way to obtain the desired section order.
Here is my code to help you find the issue.
#import "ToDoItemsTableViewController.h"
#import "AppDelegate.h"
#import "AddToDoItemViewController.h"
#import "ToDoSubItemsTableViewController.h"
#interface ToDoItemsTableViewController ()<UIAlertViewDelegate>
#property (nonatomic, strong)NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong)NSFetchedResultsController *fetchedResultsController;
#end
#implementation ToDoItemsTableViewController
#synthesize searchResults;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(NSManagedObjectContext *)managedObjectContext{
return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//navigation bar background image
[self.navigationController.navigationBar
setBackgroundImage:[UIImage imageNamed:#"navBar.png"]
forBarMetrics:UIBarMetricsDefault];
NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor],NSForegroundColorAttributeName,
[UIColor whiteColor],NSBackgroundColorAttributeName,nil];
self.navigationController.navigationBar.titleTextAttributes = textAttributes;
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"navBar"]];
NSError *error = nil;
if (![[self fetchedResultsController]performFetch:&error]){
NSLog(#"Error %#",error);
abort();
}
self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]];
[self.tableView reloadData];
}
-(void) viewWillAppear:(BOOL)animated{
[self.tableView reloadData];
}
- (void)viewDidUnload
{
self.searchResults = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier]isEqualToString:#"addToDoItem"]){
UINavigationController *navigationController = segue.destinationViewController;
AddToDoItemViewController *addToDoItemViewController = (AddToDoItemViewController*)navigationController.topViewController;
ToDoItem *addToDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"ToDoItem" inManagedObjectContext:self.managedObjectContext];
addToDoItem.todoDueDate = [NSDate date];
addToDoItemViewController.addToDoItem = addToDoItem;
}
if ([[segue identifier] isEqualToString:#"toToDoSubItems"]){
ToDoSubItemsTableViewController *todoSubItemsTableViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ToDoItem *selectedToDoItem = (ToDoItem*)[self.fetchedResultsController objectAtIndexPath:indexPath];
todoSubItemsTableViewController.selectedToDoItem = selectedToDoItem;
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return 1;
}
else
{
return [[self.fetchedResultsController sections]count];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else {
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];
// Configure the cell...
ToDoItem *toDoItem = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
if (cell==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
NSLog(#"Configuring cell to show search results");
toDoItem = [self.searchResults objectAtIndex:indexPath.row];
cell.textLabel.text = toDoItem.todoName;
NSDate *fechaToDO = toDoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
else
{
ToDoItem *todoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = todoItem.todoName;
NSDate *fechaToDO = todoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *header = #"customHeader";
UITableViewHeaderFooterView *vHeader;
vHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:header];
if (!vHeader) {
vHeader = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:header];
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
if (section == 0) {
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
else if (section == 1) {
vHeader.textLabel.backgroundColor = [UIColor orangeColor];
vHeader.textLabel.textColor = [UIColor blueColor];
vHeader.contentView.backgroundColor = [UIColor orangeColor];
}
else if (section == 2) {
vHeader.textLabel.backgroundColor = [UIColor greenColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor greenColor];
}
else if (section == 3) {
vHeader.textLabel.backgroundColor = [UIColor greenColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor greenColor];
}
else if (section == 4) {
vHeader.textLabel.backgroundColor = [UIColor blueColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor blueColor];
}
vHeader.textLabel.text = [self tableView:tableView titleForHeaderInSection:section];
return vHeader;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if (tableView == self.searchDisplayController.searchResultsTableView){
NSString *valor = [NSString stringWithFormat:#"S E A R C H R E S U L T S (%d)",[self.searchResults count]];
return valor;
}
else {
id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections]objectAtIndex:section];
NSString *sectionname = [theSection name];
if ([sectionname isEqualToString:#"0"]){
NSString *valor = [NSString stringWithFormat:#"O V E R D U E (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:#"1"]){
NSString *valor = [NSString stringWithFormat:#"T O D A Y (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:#"2"]){
NSString *valor = [NSString stringWithFormat:#"T O M O R R O W (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:#"3"]){
NSString *valor = [NSString stringWithFormat:#"U P C O M I N G (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:#"4"]){
NSString *valor = [NSString stringWithFormat:#"S O M E D A Y (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
if ([[self.fetchedResultsController sections]count]>0){
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo name];
}
else{
return nil;
}
}
}
#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*)fetchedResultsController{
if (_fetchedResultsController != nil){
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSManagedObjectContext *context = self.managedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ToDoItem" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"todoDueDate" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:#"todoName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor,sortDescriptor1, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:#"sectionIdentifier" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - Fetched Results Controller Delegates
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
-(void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{
UITableView *tableView = self.tableView;
switch (type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:{
ToDoItem *changeToDoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = changeToDoItem.todoName;
NSDate *fechaToDO = changeToDoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
-(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;
}
}
// 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 NO;
}
// Override to support editing the table view.
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#pragma mark -
#pragma mark Content Filtering
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
self.searchResults = [[self.fetchedResultsController fetchedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
ToDoItem * item = evaluatedObject;
NSString* name = item.todoName;
//searchText having length < 3 should not be considered
if (!!searchText && [searchText length] < 3) {
return YES;
}
if ([scope isEqualToString:#"All"] || [name isEqualToString:scope]) {
return ([name rangeOfString:searchText].location != NSNotFound);
}
return NO; //if nothing matches
}]];
}
#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:#"All"];
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:#"All"];
return YES;
}
- (IBAction)quickAddAction:(UIButton *)sender {
UIAlertView * alert =[[UIAlertView alloc ] initWithTitle:#"Add Task" message:#"Enter the task name" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles: nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert addButtonWithTitle:#"Add"];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
UITextField *todoText = [alertView textFieldAtIndex:0];
NSLog(#"username: %#", todoText.text);
ToDoItem *addToDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"ToDoItem" inManagedObjectContext:self.managedObjectContext];
addToDoItem.todoDueDate = [NSDate date];
NSString *todoConvertido = todoText.text;
addToDoItem.todoName = todoConvertido;
[self.tableView reloadData];
}
}
#end
you sort only based on due Date and name so the category with the oldest entry comes first.
the entries would have to be sorted based on your sectionIdentifier first
NSSortDescriptor *sortDescriptor0 = [[NSSortDescriptor alloc]initWithKey:#"sectionIdentifier" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:#"todoDueDate" ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc]initWithKey:#"todoName" ascending:YES];

Search bar implementation not working

I am following Tim Roadley tutorial http://timroadley.com/2012/03/05/core-data-basics-part-7-search-bars/ trying to add a search bar to my project, but I am receiving an exception when executing my app. This is the exception:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'.
And this is my code, updated with the tutorial code.
#import "ToDoItemsTableViewController.h"
#import "AppDelegate.h"
#import "AddToDoItemViewController.h"
#import "ToDoSubItemsTableViewController.h"
#interface ToDoItemsTableViewController ()
#property (nonatomic, strong)NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong)NSFetchedResultsController *fetchedResultsController;
#end
#implementation ToDoItemsTableViewController
#synthesize searchResults;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(NSManagedObjectContext *)managedObjectContext{
return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//navigation bar background image
[self.navigationController.navigationBar
setBackgroundImage:[UIImage imageNamed:#"navBar.png"]
forBarMetrics:UIBarMetricsDefault];
NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor blackColor],NSForegroundColorAttributeName,
[UIColor blackColor],NSBackgroundColorAttributeName,nil];
self.navigationController.navigationBar.titleTextAttributes = textAttributes;
NSError *error = nil;
if (![[self fetchedResultsController]performFetch:&error]){
NSLog(#"Error %#",error);
abort();
}
self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]];
[self.tableView reloadData];
}
-(void) viewWillAppear:(BOOL)animated{
[self.tableView reloadData];
}
- (void)viewDidUnload
{
self.searchResults = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier]isEqualToString:#"addToDoItem"]){
UINavigationController *navigationController = segue.destinationViewController;
AddToDoItemViewController *addToDoItemViewController = (AddToDoItemViewController*)navigationController.topViewController;
ToDoItem *addToDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"ToDoItem" inManagedObjectContext:self.managedObjectContext];
addToDoItem.todoDueDate = [NSDate date];
addToDoItemViewController.addToDoItem = addToDoItem;
}
if ([[segue identifier] isEqualToString:#"toToDoSubItems"]){
ToDoSubItemsTableViewController *todoSubItemsTableViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ToDoItem *selectedToDoItem = (ToDoItem*)[self.fetchedResultsController objectAtIndexPath:indexPath];
todoSubItemsTableViewController.selectedToDoItem = selectedToDoItem;
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections]count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else {
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 forIndexPath:indexPath];
// Configure the cell...
ToDoItem *toDoItem = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
NSLog(#"Configuring cell to show search results");
toDoItem = [self.searchResults objectAtIndex:indexPath.row];
}
else
{
ToDoItem *todoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = todoItem.todoName;
NSDate *fechaToDO = todoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *header = #"customHeader";
UITableViewHeaderFooterView *vHeader;
vHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:header];
if (!vHeader) {
vHeader = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:header];
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
if (section == 0) {
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
else if (section == 1) {
vHeader.textLabel.backgroundColor = [UIColor orangeColor];
vHeader.textLabel.textColor = [UIColor blueColor];
vHeader.contentView.backgroundColor = [UIColor orangeColor];
}
else if (section == 2) {
vHeader.textLabel.backgroundColor = [UIColor greenColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor greenColor];
}
vHeader.textLabel.text = [self tableView:tableView titleForHeaderInSection:section];
return vHeader;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections]objectAtIndex:section];
NSString *sectionname = [theSection name];
if ([sectionname isEqualToString:#"0"]){
NSString *valor = [NSString stringWithFormat:#"O V E R D U E (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:#"1"]){
NSString *valor = [NSString stringWithFormat:#"T O D A Y (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
else if ([sectionname isEqualToString:#"2"]){
NSString *valor = [NSString stringWithFormat:#"U P C O M I N G (%d)", [self.tableView
numberOfRowsInSection:section]];
return valor;
}
if ([[self.fetchedResultsController sections]count]>0){
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo name];
}
else{
return nil;
}
}
#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*)fetchedResultsController{
if (_fetchedResultsController != nil){
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSManagedObjectContext *context = self.managedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ToDoItem" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"todoDueDate" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:#"todoName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor,sortDescriptor1, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:#"sectionIdentifier" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - Fetched Results Controller Delegates
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
-(void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{
UITableView *tableView = self.tableView;
switch (type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:{
ToDoItem *changeToDoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = changeToDoItem.todoName;
NSDate *fechaToDO = changeToDoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
-(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;
}
}
/*
// 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
NSManagedObjectContext *context = [self managedObjectContext];
ToDoItem *ToDoItemToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:ToDoItemToDelete];
NSError *error = nil;
if (![context save:&error]){
NSLog(#"Error: %#",error);
}
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#pragma mark -
#pragma mark Content Filtering
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSLog(#"Previous Search Results were removed.");
[self.searchResults removeAllObjects];
for (ToDoItem *toDoItem in [self.fetchedResultsController fetchedObjects])
{
if ([scope isEqualToString:#"All"] || [toDoItem.todoName isEqualToString:scope])
{
NSComparisonResult result = [toDoItem.todoName compare:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame)
{
NSLog(#"Adding toDoItem.todoName '%#' to searchResults as it begins with search text '%#'", toDoItem.todoName, searchText);
[self.searchResults addObject:toDoItem];
}
}
}
}
#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:#"All"];
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:#"All"];
return YES;
}
#end
Any advice or help is welcome.
Try to correct your code in this way :
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
you should notice that:
Important: You must register a class or nib file using the
registerNib:forCellReuseIdentifier: or
registerClass:forCellReuseIdentifier: method before calling this
method.
This is different method :
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
See documentation : https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier%3a

Putting number of rows in section title

I would need to include the number of rows in the section title, like TODAY (6), that means that on section titled TODAY there are 6 rows (core data objects in my case). I know that it is to find here:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
But I don't know how to include this on each section to be shown as a label text.
Any advice is welcome....
#import "ToDoItemsTableViewController.h"
#import "AppDelegate.h"
#import "AddToDoItemViewController.h"
#import "ToDoSubItemsTableViewController.h"
#interface ToDoItemsTableViewController ()
#property (nonatomic, strong)NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong)NSFetchedResultsController *fetchedResultsController;
#end
#implementation ToDoItemsTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(NSManagedObjectContext *)managedObjectContext{
return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *error = nil;
if (![[self fetchedResultsController]performFetch:&error]){
NSLog(#"Error %#",error);
abort();
}
}
-(void) viewWillAppear:(BOOL)animated{
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier]isEqualToString:#"addToDoItem"]){
UINavigationController *navigationController = segue.destinationViewController;
AddToDoItemViewController *addToDoItemViewController = (AddToDoItemViewController*)navigationController.topViewController;
ToDoItem *addToDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"ToDoItem" inManagedObjectContext:self.managedObjectContext];
addToDoItemViewController.addToDoItem = addToDoItem;
}
if ([[segue identifier] isEqualToString:#"toToDoSubItems"]){
ToDoSubItemsTableViewController *todoSubItemsTableViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ToDoItem *selectedToDoItem = (ToDoItem*)[self.fetchedResultsController objectAtIndexPath:indexPath];
todoSubItemsTableViewController.selectedToDoItem = selectedToDoItem;
}
}
#pragma mark - Table view data source
- (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];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
ToDoItem *todoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = todoItem.todoName;
NSDate *fechaToDO = todoItem.todoDueDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"EEEE, dd MMMM YYYY"];
NSString *fechaToDo = [dateFormatter stringFromDate:fechaToDO];
cell.detailTextLabel.text = fechaToDo;
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *header = #"customHeader";
UITableViewHeaderFooterView *vHeader;
vHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:header];
if (!vHeader) {
vHeader = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:header];
vHeader.textLabel.backgroundColor = [UIColor redColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor redColor];
}
if (section == 1) {
vHeader.textLabel.backgroundColor = [UIColor blueColor];
vHeader.textLabel.textColor = [UIColor whiteColor];
vHeader.contentView.backgroundColor = [UIColor blueColor];
} else {
[vHeader setBackgroundColor:[UIColor redColor]];
}
vHeader.textLabel.text = [self tableView:tableView titleForHeaderInSection:section];
return vHeader;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections]objectAtIndex:section];
NSString *sectionname = [theSection name];
if ([sectionname isEqualToString:#"0"]){
return #"Overdue";
}
else if ([sectionname isEqualToString:#"1"]){
return #"Today";
}
else if ([sectionname isEqualToString:#"2"]){
return #"Upcoming";
}
if ([[self.fetchedResultsController sections]count]>0){
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections]objectAtIndex:section];
return [sectionInfo name];
}
else{
return nil;
}
}
#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*)fetchedResultsController{
if (_fetchedResultsController != nil){
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSManagedObjectContext *context = self.managedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ToDoItem" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"todoDueDate" ascending:YES];
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:#"todoName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor,sortDescriptor1, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:#"sectionIdentifier" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - Fetched Results Controller Delegates
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
-(void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{
UITableView *tableView = self.tableView;
switch (type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:{
ToDoItem *changeToDoItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = changeToDoItem.todoName;
cell.detailTextLabel.text = changeToDoItem.todoDescription;
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
-(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;
}
}
/*
// 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
NSManagedObjectContext *context = [self managedObjectContext];
ToDoItem *ToDoItemToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:ToDoItemToDelete];
NSError *error = nil;
if (![context save:&error]){
NSLog(#"Error: %#",error);
}
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
[NSString stringWithFormat:#"Today(%d)", [tableView numberOfRowsInSection:
section]];

[UIBarButtonItem _isAncestorOfFirstResponder]: unrecognized selector sent to instance

This code works perfectly in one app and crashes in another with message:
[UIBarButtonItem _isAncestorOfFirstResponder]: unrecognized selector sent to instance
If I comment the magical record code I can see that method runs OK.
- (void)viewDidLoad{
[super viewDidLoad];
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addNote:)];
self.navigationItem.rightBarButtonItem = addButton;
}
- (IBAction)addNote:(id)sender{
NSLog(#"%s",__PRETTY_FUNCTION__);
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
Note *note = [Note MR_createInContext:localContext];
NSDate *now = [NSDate date];
note.date = now;
note.person = _person;
[localContext MR_saveWithOptions:MRSaveSynchronously completion:^(BOOL success, NSError *error) {
UIStoryboard *sb = [UIStoryboard storyboardWithName:NSBundle.mainBundle.infoDictionary[#"UIMainStoryboardFile"] bundle:NSBundle.mainBundle];
NoteViewController *vc = [sb instantiateViewControllerWithIdentifier:#"NoteViewController"];
vc.note = note;
[self.navigationController pushViewController:vc animated:YES];
}];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UILabel *noResultsLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.width)];
noResultsLabel.textColor = [UIColor colorWithWhite:0.557 alpha:1.000];
noResultsLabel.font = [UIFont boldSystemFontOfSize:35];
noResultsLabel.textAlignment = NSTextAlignmentCenter;
noResultsLabel.text = NSLocalizedString(#"No notes", nil);
self.tableView.nxEV_emptyView = noResultsLabel;
self.fetchedResultsController.delegate = self;
[self.fetchedResultsController performFetch:nil];
[self.tableView reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
_fetchedResultsController.delegate = nil;
}
#pragma mark - Fetched results controller
- (void)dealloc
{
NSLog(#"%s",__PRETTY_FUNCTION__);
self.fetchedResultsController.delegate = nil;
self.fetchedResultsController = nil;
}
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"person == %#", _person];
self.fetchedResultsController = [Note MR_fetchAllGroupedBy:#"source" withPredicate:predicate sortedBy:#"source,date" ascending:YES delegate:self];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[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)selectCreatedRowatIndexPath:(NSIndexPath *)indexPath{
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:(NoteCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
[self.tableView reloadData];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
if (sectionInfo.name.intValue == 0) {
return NSLocalizedString(#"Not Secret", #"Notes");
}else return NSLocalizedString(#"Secret", #"Notes");
}
- (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];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Note Cell";
NoteCell *cell = (NoteCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(NoteCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Note *note = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.dateLabel.text = [[CZDateFormatterCache mainQueueCache] localizedStringFromDate:note.date dateStyle:kCFDateFormatterLongStyle timeStyle:kCFDateFormatterShortStyle];
if (note.note.length > 0) {
cell.noteLabel.text = note.note;
} else {
cell.noteLabel.text = NSLocalizedString(#"New Note", nil);
}
cell.rateView.rate = [note.trustworthy intValue];
NSLog(#"note.trustworthy intValue %i", [note.trustworthy intValue]);
cell.rateView.backgroundColor = [UIColor clearColor];
cell.backgroundColor = [UIColor whiteColor];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext) {
[[self.fetchedResultsController objectAtIndexPath:indexPath] MR_deleteInContext:localContext];
} completion:^(BOOL success, NSError *error) {
//
}];
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender {
if ([segue.identifier isEqualToString:#"Note Segue"]) {
NSLog(#"%s",__PRETTY_FUNCTION__);
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Note *note = [[self fetchedResultsController] objectAtIndexPath:indexPath];
NoteViewController *anvc = segue.destinationViewController;
anvc.note = note;
}
}
OK, the problem was in the second view controller.
I found it occasionally.
I used UIBarButtonItem with custom view as a navigation bar titleView.

UILabels are dissappearing from the table view cell content view when scrolling off, but if cell is selected are shown again

I have a custom table view cell with two uilabels everything starts normally but when i scroll to another part of the table and come back, the label are not found anywhere.But then if i select them they are shown again until they are deselected
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
id appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"%# %#", error, [error userInfo]);
abort();
}
_infoView.layer.cornerRadius = 5;
_infoView.layer.masksToBounds = YES;
_infoView.layer.shadowColor = [UIColor colorWithRed:205.0/255.0 green:205.0/255.0 blue:205.0/255.0 alpha:1.0].CGColor;
_infoView.layer.shadowOpacity = 0.8;
_infoView.layer.shadowRadius = 10.0;
_infoView.layer.shadowOffset = CGSizeMake(2.0, 2.0);
_addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(add:)];
self.navigationItem.rightBarButtonItem = _addButton;
_searchBar.backgroundColor = [UIColor clearColor];
_searchBar.clipsToBounds = YES;
_searchBar.tintColor = [UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:1.0];
for (UIView *subview in _searchBar.subviews)
{
if ([subview isKindOfClass:NSClassFromString(#"UISearchBarBackground")])
{
[subview removeFromSuperview];
break;
}
}
_exercisesNumberLabel.text = [NSString stringWithFormat:#"%lu Exercises", (unsigned long)[_fetchedResultsController.fetchedObjects count]];
[_exercisesNumberLabel sizeToFit];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.tableView setContentOffset:CGPointMake(0, _headerView.bounds.size.height)];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)add:(id)sender
{
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[_fetchedResultsController sections] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[[_fetchedResultsController sections] objectAtIndex:section] name];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = nil;
cellIdentifier = #"exerciseCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
[self stampCell:cell atIndexPath:indexPath];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)stampCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
UILabel *textLabel, *detailTextLabel;
UIButton *playButton;
//UIWebView *miniYouTubeView;
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 2, 170, 22)];
textLabel.tag = kExerciseCellTextLabel;
textLabel.font = [UIFont systemFontOfSize:17.0];
textLabel.textAlignment = NSTextAlignmentLeft;
textLabel.textColor = [UIColor blackColor];
[[cell contentView] addSubview:textLabel];
detailTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 24, 170, 18)];
detailTextLabel.tag = kExerciseCellDetailTextLabel;
detailTextLabel.font = [UIFont systemFontOfSize:14.0];
detailTextLabel.textAlignment = NSTextAlignmentLeft;
detailTextLabel.textColor = [UIColor colorWithRed:128.0/255.0 green:128.0/255.0 blue:128.0/255.0 alpha:1.0];
detailTextLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
[[cell contentView] addSubview:detailTextLabel];
playButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 64, 44)];
playButton.backgroundColor = [UIColor lightGrayColor];
[playButton setImage:[UIImage imageNamed:#"121-landscape.png"] forState:UIControlStateNormal];
[[cell contentView] addSubview:playButton];
/*miniYouTubeView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 60, 44)];
miniYouTubeView.tag = kExerciseCellMiniYouTubeView;
miniYouTubeView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight;
[[cell contentView] addSubview:miniYouTubeView];*/
}
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[[_fetchedResultsController objectAtIndexPath:indexPath] isDefault] boolValue]) {
return NO;
}
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleInsert) {
}
else if (editingStyle == UITableViewCellEditingStyleDelete) {
Exercise *exercise = [_fetchedResultsController objectAtIndexPath:indexPath];
[_managedObjectContext deleteObject:exercise];
NSError *error;
if (![_managedObjectContext save:&error]) {
NSLog(#"%# %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - NSFetchedResultsControllerDelegate
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kExercise inManagedObjectContext:_managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:kExerciseName ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:_managedObjectContext sectionNameKeyPath:kExerciseFirstLetter cacheName:#"ExerciseList"];
[self setFetchedResultsController:fetchedResultsController];
[_fetchedResultsController setDelegate:self];
return _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[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)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Exercise *exercise = [_fetchedResultsController objectAtIndexPath:indexPath];
UILabel *textLabel = (UILabel *)[[cell contentView] viewWithTag:kExerciseCellTextLabel];
UILabel *detailTextLabel = (UILabel *)[[cell contentView] viewWithTag:kExerciseCellDetailTextLabel];
//UIWebView *miniYouTubeView = (UIWebView *)[[cell contentView] viewWithTag:kExerciseCellMiniYouTubeView];
textLabel.text = [exercise valueForKey:kExerciseName];
detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", [[exercise valueForKey:kExerciseEType] valueForKey:kExerciseTypeName], [[exercise valueForKey:kGear] valueForKey:kGearName]];
//[textLabel sizeToFit];
//[detailTextLabel sizeToFit];
/*[miniYouTubeView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[exercise valueForKey:kExerciseUrlAddress]]]];
[miniYouTubeView setScalesPageToFit:YES];
[miniYouTubeView setAutoresizesSubviews:YES];*/
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Cells get reused as the table is scrolled. But your code is written in such a way that you keep adding more and more subviews each time the cell is reused.
You should only call stampCell if cell is nil.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = #"exerciseCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
[self stampCell:cell atIndexPath:indexPath];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
An even better solution would be to subclass UITableViewCell and put all of this logic in the cell instead of the view controller.

Resources