user1904273
user1904273

Reputation: 4764

ios/objective-c: Get count of array before table loads

I am populating a tableview with the contents of an array. Right now, I create the array in viewdidload and I calculate the number of rows in the delegate method

//in viewdidload

dispatch_async(kBgQueue, ^{
        NSData* data = [NSData dataWithContentsOfURL: kItemsURL];
        [self performSelectorOnMainThread:@selector(fetchedData:) withObject:data waitUntilDone:YES];
    });

    [self.tableView reloadData];

//method called in viewdidload to create array...
- (void)fetchedData:(NSData *)responseData {
    NSError* error;
    NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData //1
                                                         options:kNilOptions
                                                           error:&error];
    NSLog(@" %@",json);
    NSArray* latestItems = [json objectForKey:@"items"];
    NSLog(@" array:%@",latestItems);
//getItems is a property in .h file
    self.getItems = latestItems;
    NSLog(@"getItems %@",_getItems); //logs out array ok
    int size = [_getItems count];
    NSLog(@"there are %d objects in the array", size);//provides correct number
}


    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 NSLog(@"getItems %@",_getItems); //logs (null)
    int size = [_getItems count];
    NSLog(@" %d objects in the array", size);//logs 0

When I count rows in viewdidload after creating the array, I get the correct number, however, when I call count on the array in the delegate method, it returns zero possibly because the tableview is created before Viewdidload is called.

Where should I create the array so that is known by the time numberofrows counts the number of rows in the array?

Edit:

After constructing the array, I save it to a property. However, I have discovered that this property is empty when I then log it to console in the numberofrowsinsection method so the problem seems to lie in how I am storing this array.

Right now, I have a property in the .h file and I've also tried it in the implementation but either way it is not persisting for some reason.

Upvotes: 0

Views: 898

Answers (3)

Allan
Allan

Reputation: 317

I suggest to load the content of your array in viewDidLoad(), that is called once and before the table view use the array. The table view do not load the items before viewDidLoad. Are you doing something much different than this example structure below?

@implementation ViewController {
    NSArray *arrayList;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    arrayList = @[@"item 1", @"item 2"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    cell.textLabel.text = [arrayList objectAtIndex:indexPath.row];
    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return arrayList.count;
}

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

Upvotes: 1

Yonny
Yonny

Reputation: 402

I'm not to familiar with obj-C, but I know you need to initialize your array outside your viewDidLoad() function. The reason why your .count is returning zero, is because your array is acting as a local variable to your viewDidLoad() function. Instead you could initialize the array as field in your UITableViewController class. This is how you would do so in swift, but it applies to obj-C as well:

class YourTableViewController: UITableViewController {

    var yourArray = [AnyObject]()

    override func viewDidLoad() {

        //You can still do any programming to set up values and elements in yourArray[] here 
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return yourArray.count
    }

    //Plus all your other tableView functions...
}

Also if you are passing information to your array between other UIViewController's you can add this function to your class, so every time you come back to your table view it loads the correct table cell count:

override func viewWillAppear(animated: Bool) {
    self.tableView.reloadData()
}

Upvotes: 1

Lim Jing Rong
Lim Jing Rong

Reputation: 426

Consider abstracting the creation of your data - the array instantiated in your tableview, into a model instead. This is generally considered to be a better software engineering practice (read : https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html ).

What I would do is have another file as a Class or Struct, and populate the data for the array used in your table view in there. I would also recommend having setter/getter methods in your array class/struct as well. When loading the tableview, we would then grab the data from the class/struct in your tableview viewDidLoad() method. The data from your array would also be available at any other point of your application as well, as it is no longer dependant on the tableview.

Side note : You can consider making the class/struct a singleton as well, if the model is supposed to only get instantiated once.

Upvotes: 0

Related Questions