0

my app is coreData based, uses mapKit, and spot annotations. The app runs with all it's functionalities; the main issue is that when i input a new location on this text field, this new spot does not appear in the Table View like it should. Only when I restart the app, the table is refreshed and the new spot is available despite having the tableview reload instruction. Does anyone have a clue why this happens and how I can fix it? Thank you. The code for the table view:

@interface TableViewController ()

@property (strong) NSMutableArray *lisbonSpots;


@end

@implementation TableTableViewController

- (IBAction)delete:(UIBarButtonItem *)sender {
     self.tableView.editing = !self.tableView.editing;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    //_bar=[Spot spotType:@"bar"];


    self.tableView.dataSource = self;

    _lisbonSpots = [[Spot allSpots]mutableCopy];
    NSLog(@"The Core Spots are: %@", _lisbonSpots);

    [self.tableView reloadData];

}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.lisbonSpots.count;

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    NSManagedObject *ls = [self.lisbonSpots objectAtIndex:indexPath.row];
    NSLog(@"Table Spots are: %@", ls);
    [cell.textLabel setText:[NSString stringWithFormat:@"%@", [ls valueForKey:@"name"]]];
    cell.imageView.image = [UIImage imageNamed:@"city.jpg"];
    return cell;
}
FuManchu
  • 145
  • 2
  • 11

2 Answers2

1

I believe the issue you are having is due to calling reloadData inside viewDidLoad.

Only when I restart the app, the table is refreshed and the new spot is available despite having the tableview reload instruction

viewDidLoad should be used for initial setup work or "one-time" only work when setting up your view controller. It is most likely only called ONCE per application launch. For more information on view controller lifecycles refer to this answer: Looking to understand the iOS UIViewController lifecycle.

Try moving your reloadData call to viewDidAppear like this:

- (void)viewDidAppear {
    [super viewDidAppear];
    _lisbonSpots = [[Spot allSpots]mutableCopy];

    [self.tableView reloadData];
}
Community
  • 1
  • 1
A.C. Wright
  • 921
  • 9
  • 21
  • It didnt work, the issue remains...But other strange thing is that (haven't explained) the pin appears on the map in the same app session, but not its name in the table...Sorry for the late reply – FuManchu Feb 16 '17 at 12:14
  • Your answer is right, but one line was missing: _lisbonSpots = [[Spot allSpots]mutableCopy]; The method must contain the source data. Though, the credit is yours, thanks :) – FuManchu Feb 17 '17 at 13:32
0

Try fetching the data with NSFetchedResultscontroller: Following code in a single method that is called on initialize, create an instance variable for NSFetchedResultscontroller *fetchedController;

NSManagedObjectContext *context = <#Managed object context#>;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Configure the request's entity, and optionally its predicate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"<#Sort key#>" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];

NSFetchedResultsController *controller = [[NSFetchedResultsController alloc]
    initWithFetchRequest:fetchRequest
    managedObjectContext:context
    sectionNameKeyPath:nil
    cacheName:@"<#Cache name#>"];
[fetchRequest release];

NSError *error;
BOOL success = [controller performFetch:&error];

And the tableView Delegate methods, the fetchedResultsController does the fetching process after inserting or removing for you. (Code is from Apple Docs)

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[<#Fetched results controller#> sections] count];
}

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection (NSInteger)section {
    if ([[<#Fetched results controller#> sections] count] > 0) {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[<#Fetched results controller#> sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
} else
    return 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   UITableViewCell *cell = <#Get the cell#>; // Your chase [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
   NSManagedObject *managedObject = [<#Fetched results controller#> objectAtIndexPath:indexPath];
   // Configure the cell with data from the managed object.
   return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if ([[<#Fetched results controller#> sections] count] > 0) {
    id <NSFetchedResultsSectionInfo> sectionInfo = [[<#Fetched results controller#> sections] objectAtIndex:section];
    return [sectionInfo name];
} else
    return nil;
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return [<#Fetched results controller#> sectionIndexTitles];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [<#Fetched results controller#> sectionForSectionIndexTitle:title atIndex:index];
}

Hope it helps you out!

Community
  • 1
  • 1
voltae
  • 582
  • 4
  • 11
  • Thanks for the answer, but I've never used this controller and I'm on a tight scheduele...It has to be a solution – FuManchu Feb 16 '17 at 12:16
  • Give it a try. It is worth! It is simplier than it looks. Just try to implement the declaration of the NSFetchedResultscontroller as a function called after windowDidLoad, and the rest is straightforward. – voltae Feb 16 '17 at 12:39