2

I am trying to update a UITableViewCell as soon as the user's location is found and reverse-geocoded.

From reading lots of other answers to similar questions, it seems the tableview reload must occur on the main thread, which I have tried without any success.

All the location data gets retrieved correctly, and is correctly added to the core data object, but the tableview cell simply is not updating until the user scrolls or the cell is selected, at which point the cell is correctly updated from that point on.

Here is a selection from my code - does anyone know why the tableview cell isn't updating right away?

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations  // Delegate callback method.
{       

    // Correctly gets currentLocation coordinates.
    ...
    CLLocation *currentLocation = [locations lastObject];
    ...

    // Reverse-geocode the coordinates (find physical address):
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {

        if (error == nil && [placemarks count] > 0) {
            CLPlacemark *placemark = [placemarks lastObject]; // Correctly gets placemark.

            //    Correctly adds placemark to core data object.
            ...
            ...

            // Reload TableView:
            //    [self.tableView reloadData];  //Tried this, didn't work, since not on main thread.
            //    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];  //Doesn't work.
            //    [self performSelector:(@selector(refreshDisplay)) withObject:nil afterDelay:0.5];  //Doesn't work.
            [self performSelectorOnMainThread:@selector(refreshDisplay) withObject:nil waitUntilDone:NO];  //Doesn't work.
        }
    }];
}

- (void)refreshDisplay {
    [_tableView reloadData];
}

Again, the underlying logic is working, since the data gets added correctly and eventually shows up on the cell, but not until user scroll or selection. I can't imagine why this doesn't refresh the tableviewcell right away. Does anyone have any idea?

UPDATE: My Solution

The missing piece was adding [cell layoutSubviews] just after the cell is created/dequeued. The detailTextLabel now updates correctly. Apparently this may be related to an iOS8 bug that doesn't update the detailText if it starts out nil (i.e. no content), and layoutSubviews makes it so it is not nil, by initializing all the subviews of the cell (as far as I understand). I got this suggestion from here:

ios 8 UITableViewCell detail text not correctly updating

The accepted answer also helped me figure out this missing piece.

pkamb
  • 33,281
  • 23
  • 160
  • 191
autobahn
  • 115
  • 1
  • 10

3 Answers3

1

You should get a reference to the cell that you want to update

Ex. UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:theRow inSection:theSection]];

Then [[cell textLabel] setText:theLocation];

If your updating multiple cells just get multiple references of the cells you want to update and update them accordingly.

Typically anything dealing with UI components that need updating should be done on the main thread. I have come across this issue before but if you want to have a solution dealing with threading, what you have done seems like it should work.

Here is the GCD solution:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.table reloadData];
});

But according to what you've done, it shouldn't help... It is basically the same thing just with GCD. Hopefully the solution I gave you at the beginning works...

EDIT

Within your - (UITableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath

    cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];

Did you set the style to UITableViewCellStyleDefault?

jsetting32
  • 1,632
  • 2
  • 20
  • 45
  • Thanks for the quick response! I tried your suggestion, and the strange thing is that it works if it is modifying the textLabel, but I need it to modify the detailTextLabel (subtitle label), and when I simply change `[[cell textLabel]...` to `[[cell detailTextLabel]...`, it no longer works (I assume because it is only updating a part of the cell, rather than the entire thing). I have put everything into a dispatch_async block, as you suggested. – autobahn Jan 09 '15 at 18:03
  • I am using `UITableViewCellStyleSubtitle`, since the location data goes into the subtitle. I don't alloc-init it like this though, it is set up in the storyboard and then retrieved using a cell dequeue, like so: `UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];` – autobahn Jan 09 '15 at 18:10
  • 1
    Hmm... So the `detailTextLabel` isn't being updated but the `textLabel` is? This is weird... Ill get back to you – jsetting32 Jan 09 '15 at 18:12
  • Well, if I tell it to update the textLabel, then I think it is just nuking the whole cell UI and creating a new one, since there is no detailText that is set yet (so I can't really tell). In other words, textLabel does update (I think by recreating the whole cell from scratch), but detailTextLabel does not update using the same method for some reason. – autobahn Jan 09 '15 at 18:15
  • 1
    I think I may have figured it out. It seems I needed to add `[cell layoutSubviews];` just after the cell is created/dequeued. This properly updates the detailTextLabel now, based on the methods you described above. Apparently this may be related to an iOS8 bug that doesn't update the detailText if it starts out nil, and layoutSubviews makes it so it is not nil, by initializing the subviews of the cell (as far as I understand). I got this suggestion from here: http://stackoverflow.com/a/27003639/3629626. I'm marking this as the right answer though, since it helped lead me to this solution :) – autobahn Jan 09 '15 at 18:57
  • 1
    Sweet! I'm glad you solved the issue. And I'm happy I helped you get on the right path. – jsetting32 Jan 09 '15 at 18:59
0

It seems that tableview cell is not completely visible in the view.In that case You can use [cell setNeedsDisplay]; for example: dispatch_async(dispatch_get_main_queue(), ^{ [cell setNeedsDisplay];

    [cell.contentView addSubview:yourView];
});

Hope this works for you.

0

I had the same problem. None of the answers here worked for me. I finally searched thru every aspect of the nib and saw that my controls (buttons and the table view) were not connected to outlets even though in the .h file the circle indicator was selected. But in the connections inspector they were not connected to outlets. So had to delete all the .h file controls and reconnect and low and behold everything works.

uott2
  • 41
  • 2
  • 1
    Hi, don't put all in one line. It's hard to read :-) Please learn something about posting answer on StackOverflow – piotrek1543 Dec 25 '15 at 22:06
  • Modern editors usually soft wrap (e.g. mail) and is preferable to hard cr/lf characters. How do I know how many characters each user has on one line???? – uott2 Jan 04 '16 at 08:30