0

Background: I'm working on my first iOS app that uses a UITableView for data being loaded dynamically from a web source. No, this is not homework.

Problem: When I scroll down the list bounces back to the top.

Things I've Tried:

  1. This suggestion (reducing the size of the table view) works but now I have large space at the bottom of the screen.
  2. I've tried using [tableView reloadData] but this doesn't changing the behavior. I even hooked this up to a button to make sure it was firing after the view was populated.
  3. I also read a few post about contentSize and how to calculate based on the amount of data loaded in the table. This looks like the solution I need but am having trouble getting a clear explanation of how to implement it for my setup.

Code:

I started a new project with single view application template and added a UITableView to the default view in the main storyboard.

In view controller I have the following (relevant) code:

@interface ERViewController ()
@property (nonatomic, strong) NSMutableArray *myArray;
@property (nonatomic,retain) UITableView *tableView;
@end

@implementation ERViewController
{
    NSMutableArray *tableData;
}

Here I am loading the data from Parse.com into my table and then calling [self loadView] to get the view to update after the query finishes.

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableArray *returnedData = [[NSMutableArray alloc] init];

    PFQuery *query = [PFQuery queryWithClassName:@"Persons"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            for (PFObject *object in objects) {
                //NSLog(@"display name: %@",object[@"firstName"]);
                [returnedData addObject:[NSString stringWithFormat:@"%@, %@", object[@"lastName"],object[@"firstName"]]];
            }

            tableData = returnedData;

            // Reload view to display data
            [self loadView];
        } else {
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }
    }];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"SimpleTableItem";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

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

    // Configure the cell
    cell.textLabel.text = [tableData objectAtIndex:indexPath.row];

    NSArray *itemArray = [NSArray arrayWithObjects: @"✔︎", @"?", @"X", nil];

    UISegmentedControl *mainSegment = [[UISegmentedControl alloc] initWithItems:itemArray];

    mainSegment.frame = CGRectMake(200,0, 100, 43);
    self.navigationItem.titleView = mainSegment;
    mainSegment.selectedSegmentIndex = [itemArray count];

    [mainSegment addTarget:self
                    action:@selector(mainSegmentControl:)
          forControlEvents: UIControlEventValueChanged];
    mainSegment.tag = indexPath.row;

    [cell.contentView addSubview:mainSegment];

    return cell;
}

Sample screen shot:

enter image description here


Since I'm waiting for the data to load I'm not sure where to resize the view and how exactly I need to resize the view.

Community
  • 1
  • 1
Automate This
  • 30,726
  • 11
  • 60
  • 82

2 Answers2

1

You should never ever manually call loadView.

Once you have your tableData call reloadData on the tableView.

You should also load you table data in viewDidAppear:, and if you only want to do it once, create a flag to see if its already been loaded. While waiting for the data to load, tableData will be nil so if you query the count of it, you will be messaging a nil object and therefore it would act like returning 0.

Finally you should not be touching the contentSize of the table view, it handles that itself. You just need to make sure that in Interface Builder, the table view's frame is the same as the root views frame.

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

    NSMutableArray *returnedData = [[NSMutableArray alloc] init];

    PFQuery *query = [PFQuery queryWithClassName:@"Persons"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            for (PFObject *object in objects) {
                //NSLog(@"display name: %@",object[@"firstName"]);
                [returnedData addObject:[NSString stringWithFormat:@"%@, %@", object[@"lastName"],object[@"firstName"]]];
            }

            tableData = returnedData;

            // Reload view to display data
            [self.tableView reloadData];
        } else {
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }
    }];
}

If you just want a UIViewController with only a UITableView in it, consider using a UITableViewController.

Rich
  • 8,108
  • 5
  • 46
  • 59
  • Thank you for all the helpful suggestions, obviously I'm pretty new to Objective C. When I try `reloadData` I get an error stating: `"No visible @interface for 'myViewControler' declares the selector 'reloadData'`. Is this because of how I'm connecting to the table view? You can see in my interface posted above that I declare a property for the `tableView` but maybe this is also a bad practice. – Automate This May 03 '14 at 20:26
  • Oh sorry that's a typo on my part, it should be `[self.tableView reloadData]`. I've fixed in in my answer. – Rich May 03 '14 at 20:34
  • Okay, I've moved the code over to `viewDidAppear` and am using `reloadData`. Now I went to the interface builder and stretched bottom handle of the table view down to the bottom of the view controller (snapped to blue helper line). The view still doesn't allow me to scroll down to the bottom, it bounces back to the top. Any other ideas? – Automate This May 03 '14 at 20:45
  • Are you using autolayout in your Storyboard? – Rich May 03 '14 at 20:50
  • Yes, `Use Auto Layout` is checked. I just switched the simulator over to `iPhone Retina (4 inch)` and it ran with no problems, Switched back to 3.5 inch and the problem returned. I also ran it directly on a iPhone 4s developer phone and I could scroll but not all the way to the bottom. – Automate This May 03 '14 at 20:56
  • Have you setup the constraints correctly so the table view is pinned to all the root view edges. Like I mentioned in my answer, if you only have a table view in your view controller, why not just use a table view controller? – Rich May 03 '14 at 20:57
  • I created a new `UITableViewController` as you suggested and it works. Thanks for your help! – Automate This May 03 '14 at 21:08
0

Posted for others dealing with the same problem I had and can't just move to a different view controller.

To solve the problem with a UITableView within a general view controller (not UITableViewController) click the little icon below the view controller that looks like this:

enter image description here

The button is titled "Resolve Auto Layout Issues"

Select "Reset to suggested constraints in View Controller"

This fixed all my scrolling issues since I must have been incorrectly snapping to the auto layout edges.

Automate This
  • 30,726
  • 11
  • 60
  • 82