0

I have a tableViewController that displays an "Add" (static) cell at the top and I want it to list attributes of objects (dynamic cells) pulled from a managedObjectContext. I found this post helpful in getting the "Add" cell working, but now that I've saved objects to to the managedObjectContext, I've discovered it doesn't display the attributes of the objects in the managedObjectContext.

To "see" what's going on, I made the "dynamic" cells orange. When I add categories to the managedObjectContext, the # of orange cells updates properly, but I can't get the attribute of my managedObject (an NSString) to display in the cell.

I threw a breakpoint in after my fetchRequest is completed to see if there are LocationCategories (my NSManagedObject) in the array--there are.

CategoryTVC.h

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) LocationCategory *category;

CategoryTVC.m

    #define NUMBER_OF_STATIC_CELLS 1 // this can be updated

    // Sets up an array to dump LocationCategories into
    @property (nonatomic, strong) NSArray *locationCategories;

    // cell identifier strings
    static NSString *DynamicIdentifier = @"DynamicIdentifier";
    static NSString *StaticIdentifier = @"StaticIdentifier";

 - (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    self.title = @"Select a Category";

    // Core Data
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
    self.managedObjectContext = [appDelegate managedObjectContext];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"LocationCategory" inManagedObjectContext:self.managedObjectContext]];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"categoryName" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:&sortDescriptor count:1];
    [fetchRequest setSortDescriptors:sortDescriptors];
    NSArray *categories = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
    self.locationCategories = categories; // probably duplicate to line above, but modeling Apple's sample code
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:DynamicIdentifier];
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:StaticIdentifier];

}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if (section == 0) {
        return @"";
    } else if (section == 1) {
        return @"Categories";
    } else {
        // This is just to shut up the compiler
        return nil;
    }
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 0) {
        return 1;
    } else {
        return self.locationCategories.count;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:StaticIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:StaticIdentifier];
        }

        cell.textLabel.text = @"Create new category";
        return cell;
    } else if (indexPath.section == 1) {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DynamicIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:DynamicIdentifier];
        }

        NSManagedObject *locationCategory = [self.locationCategories objectAtIndex:indexPath.row];
        cell.textLabel.text = [locationCategory valueForKey:@"categoryName"];
        cell.backgroundColor = [UIColor orangeColor]; // TODO: Gives cell a color to see how many self.locationCategories there are
        return cell;
    }
    return nil;
}

Just for the sake of completeness, I'm adding my LocationCategory class below:

**LocationCategory.h**
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class PointOfInterest;

@interface LocationCategory : NSManagedObject

@property (nonatomic, retain) id categoryColor;
@property (nonatomic, retain) NSString * categoryName;
@property (nonatomic, retain) NSSet *pointOfInterest;
@end

**LocationCategory.m**

#import "LocationCategory.h"
#import "PointOfInterest.h"

@implementation LocationCategory

@dynamic categoryColor;
@dynamic categoryName;
@dynamic pointOfInterest;

@end
Community
  • 1
  • 1
Adrian
  • 16,233
  • 18
  • 112
  • 180

2 Answers2

2

You need to call reloadData on your table view after the fetch request (so the last line in viewWillAppear).

Also, when you register a class for your cells, there's no need for an if (cell==nil) clause because your cell will never be nil.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
0

While I'm tempted to delete this question, I'm going to leave it up in case someone else makes the same (stupid) mistake I made.

@rdelmar found an updating issue, which is resolved by adding the following line to viewWillAppear in CategoryTVC.m:

[self.tableView reloadData];

I have another ViewController called AddCategoryViewController with the following properties on it.

@property (strong, nonatomic) IBOutlet UITextField *categoryNameTextField;
@property (strong, nonatomic) NSString *categoryName;

When I saved the new LocationCategory, my save did this:

- (IBAction)saveCategory:(id)sender {
    NSLog(@"Save Button Clicked");
    NSError *error;
    error = nil;
    LocationCategory *newCategory = [NSEntityDescription insertNewObjectForEntityForName:@"LocationCategory" inManagedObjectContext:self.managedObjectContext];
    newCategory.categoryName = self.categoryName; // THIS IS WRONG!!!!
    newCategory.categoryColor = self.categoryColor;
    [self.managedObjectContext save:&error];
    [[self navigationController] popViewControllerAnimated:YES];
    NSLog(@"AddCategoryViewController popped off");
}

The incorrect line above should be:

newCategory.categoryName = self.categoryNameTextField.text;

The net effect of my mistake was it dumped gibberish into my managedObjectContext and made it appear as though something was there for self.locationCategories.count's purposes.

Adrian
  • 16,233
  • 18
  • 112
  • 180