Question

I use Core Data to keep track of entries in a simple to do list. I use a simple UIAlertView with UITextField for the user to add new entries. The entries are saved using NSManagedObject, but the latest entry isn't added to the tableview, even after I run [self.tableView reloadData];

This GIF show how it works now:

Header file:

#import <UIKit/UIKit.h>

@interface PakkelisteViewController : UITableViewController <UIAlertViewDelegate>

@end

Implementation file:

#import "PakkelisteViewController.h"
#import "AUFToDoItem.h"

@interface PakkelisteViewController ()

@property NSMutableArray *toDoItems;
-(IBAction)addNewToDoItem;

@end

@implementation PakkelisteViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // defaultTodos = [[NSMutableArray alloc] initWithObjects:@"Badetøy", @"Skrivesaker", @"Lommepenger", @"Godt humør", nil];

    self.toDoItems = [[NSMutableArray alloc] init];
    [self loadInitialData];

    // 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)viewWillAppear:(BOOL)animated
{
    // Fetch the devices from persistent data store
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"AUFToDoItem"];
    self.toDoItems = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];

    [self.tableView reloadData];
}

-(void)loadInitialData
{
}

-(IBAction)addNewToDoItem
{
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Legg til ny" message:nil delegate:self cancelButtonTitle:@"Avbryt" otherButtonTitles:@"Legg til", nil];
    [alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];

    [[alertView textFieldAtIndex:0] setPlaceholder:@"Rent undertøy"];
    [[alertView textFieldAtIndex:0] setAutocapitalizationType:UITextAutocapitalizationTypeSentences];

    [alertView show];
}

-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
    NSString *inputText = [[alertView textFieldAtIndex:0] text];

    if ([inputText length] > 0)
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1)
    {
        NSManagedObjectContext *context = [self managedObjectContext];

        // Create a new managed object
        NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:@"AUFToDoItem" inManagedObjectContext:context];
        [toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:@"itemName"];
        [toDoItem setValue:[NSDate date] forKey:@"creationDate"];
        [toDoItem setValue:NO forKey:@"completed"];

        NSError *error = nil;
        // Save the object to persistent store
        if (![context save:&error]) {
            NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
        }

        [self dismissViewControllerAnimated:YES completion:nil];

        [self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade];

//      [self.tableView reloadData];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return self.toDoItems.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];
    }

    NSManagedObject *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];

    cell.textLabel.text = [toDoItem valueForKey:@"itemName"];

    if ((BOOL)[toDoItem valueForKey:@"completed"] == YES)
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    /*
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    AUFToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
    tappedItem.completed = !tappedItem.completed;

    [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
     */
}

-(NSManagedObjectContext *)managedObjectContext {
    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
    if ([delegate performSelector:@selector(managedObjectContext)]) {
        context = [delegate managedObjectContext];
    }
    return context;
}


// 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
{
    NSManagedObjectContext *context = [self managedObjectContext];

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        [context deleteObject:[self.toDoItems objectAtIndex:indexPath.row]];

        NSError *error = nil;
        if (![context save:&error])
        {
            NSLog(@"Can't delete! %@ %@", error, [error localizedDescription]);
            return;
        }

        [self.toDoItems removeObjectAtIndex:indexPath.row];
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

/*
// 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 storyboard-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
Was it helpful?

Solution

You need to add the new toDoItem to your array as well. Try this :

    // Create a new managed object
    NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:@"AUFToDoItem" inManagedObjectContext:context];
    [toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:@"itemName"];
    [toDoItem setValue:[NSDate date] forKey:@"creationDate"];
    [toDoItem setValue:NO forKey:@"completed"];

    [self.toDoItems addObject:toDoItem];
    [self.tableView reloadData];

OTHER TIPS

You should update your dataSource self.toDoItems as it still stays the same as off in viewDidLoad method. You're only saving it in CoreData, but not refreshing your dataSourse and [tableView reloadData] wont do anything

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top