1

I am loading data into my UITableViewCell one at a time in the following method

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
_anIterationCounter++;

if (_anIterationCounter==_currentCount) {
    if ((_currentCount+1)<=[_allTrains count]&&(_currentCount+1)<=5) {
        _currentCount++;
        _anIterationCounter=0;

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        dispatch_async(queue, ^{
           [tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; //call apis here
        });

    }
}

the "_iterationCount" variable is initialised to be 0 in the beginning. Data is loaded from the array [_allTrains objectAtIndex:_currentCount] and I only want to show 5 cells atmost. But my program has a further step where a didSelectRowAtIndexPath method exists. But the control doesn't go into the delegate function until all the cells are done loading. How will I resolve this issue?

Sidharth J Dev
  • 927
  • 1
  • 6
  • 25
  • I don't understand what you're trying to achieve ; why aren't you loading your cells in cellForRow? – Gil Sand May 05 '15 at 07:58

4 Answers4

3

what about doing it like so?

#import "TableViewController.h"

@interface TableViewController ()

@property (strong, nonatomic) NSArray *regularData;
@property (strong, nonatomic) NSMutableArray *lazyLoadedData;

@property (strong, nonatomic) NSTimer *insertTimer;

@end

@implementation TableViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.tableFooterView = [[UIView alloc] init];

    self.regularData = @[@"value1",
                     @"value2",
                     @"value3",
                     @"value4",
                     @"value5",
                     @"value6",
                     @"value7",
                     @"value8",
                     @"value9"];

    self.lazyLoadedData = [@[] mutableCopy];
}

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

    self.insertTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(insertRow) userInfo:nil repeats:YES];
}

- (void)insertRow {
    if (self.lazyLoadedData.count == 5) {
        // maximum reached
        [self.insertTimer invalidate];
        self.insertTimer = nil;
        return;
    }

    [self.lazyLoadedData addObject:self.regularData[self.lazyLoadedData.count]];
    [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.lazyLoadedData.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = self.lazyLoadedData[indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

@end

or take a look at my demo project: https://www.dropbox.com/sh/oe1t4u8zksalmdy/AAAJO7G32YUhXfw7ixBcIQXla?dl=0

hope i got you right. :)

André Slotta
  • 13,774
  • 2
  • 22
  • 34
  • Your answer is not in the form we want them on this site. Once the link goes away your contribution is worthless. http://meta.stackexchange.com/questions/225370/your-answer-is-in-another-castle-when-is-an-answer-not-an-answer – Anthon May 05 '15 at 07:52
1

Rather than reloading the table each time, use the tableView's insertAtIndexPaths: method to insert cells one by one.

rounak
  • 9,217
  • 3
  • 42
  • 59
0

Change the

[tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];

to

[tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

Basically I set waitUntilDone to NO.

Sanjay Mohnani
  • 5,947
  • 30
  • 46
  • That didn't work..though i really hoped it would. It made sense – Sidharth J Dev May 05 '15 at 06:24
  • @SidharthJDev why are you reloading table inside each call to willDisplayCell? – Sanjay Mohnani May 05 '15 at 06:26
  • It SORTA worked. i clicked multiple times while the tableview was loading and nothing happened. but once it was done loading, ALL the alertviews appeared sequentially(when I tap a cell, an alertview is shown) – Sidharth J Dev May 05 '15 at 06:26
  • @SidharthJDev I think rather than reloading whole table, you should use reload row at index path:index path to reload current row – Sanjay Mohnani May 05 '15 at 06:28
  • Each cell has a data that must be filled with data from an API.the API is called individually inside the "willDisplayCell". Each response takes about 5 seconds. If I dont do it like this, it takes more than 20 seconds to load the data – Sidharth J Dev May 05 '15 at 06:29
  • you mean, i should put my api query in a dispatchQueue and also a reload row at within the queue? – Sidharth J Dev May 05 '15 at 06:32
  • willDisplayCell is called for each cell, schedule api for that cell, when the api finishes you will see reflection on the corresponding cell, if you reload row at each cell creation than it will consume a lot of processing power and you will get sticky or hanging issue on main thread – Sanjay Mohnani May 05 '15 at 06:32
  • I will have a go at it – Sidharth J Dev May 05 '15 at 06:34
  • inside cellforrowatindex path or will display cell schedule api asynchrounsly and reload row inside the asynchrouns api request completion handler – Sanjay Mohnani May 05 '15 at 06:34
  • for async downloading refer -http://stackoverflow.com/questions/16663618/async-image-loading-from-url-inside-a-uitableview-cell-image-changes-to-wrong?answertab=oldest#tab-top – Sanjay Mohnani May 05 '15 at 06:39
0

Use UISCrollView and create cell object add into the scrollview then load all the cells one at a time.