Frage

The app I'm building has a lot of tables. I'm loading data for the first 15 rows, and when the user scrolls down, I'm getting the next batch of 15 rows.

I have written some DBAccess functions that takes in a 'count' and 'skip'. When loading the table initially, count = 15, skip = 0. When the user scrolls, count = 15, skip = [array count];

The code is something like this:

- (void)getDataWithCount:(NSInteger)count withSkip:(NSInteger)skip
{
    if (skip == 0)
        self.dataArray = [[NSMutableArray alloc]init];

    [DBAccess getData:self.dataArray withCount:count withSkip:skip handler:^(void)
    {
        if (no error)
            [table reloadData];
    }]; 
}

I get array out of bounds crashes in cellForRowAtIndexPath on really slow network connections (e.g., index 16 beyond empty array. numberOfRowsInSection returns [array count]).

I think the issue is as follows:

0) enter the screen.

1) Load 15 rows

2) Scroll down, load another 15. Slow connection, so I don't get a call back yet from my sendAsynchronousRequest db call

3) Go to another viewcontroller (i.e., leave the screen. I can do this because async doesn't freeze up my screen).

4) Come back into the screen. Loading initial screen sets skip = 0, hence initialises my mutable array, hits the database

5) The database hit from step 2 returns. My mutable array has been set to zero now from step 4. When reloading the table, it's trying to get self.dataArray objectAtIndex:16 etc, when the array is now empty from if(skip == 0)initialise

Does this seem about right? Any other reason why I would have array out of bounds if numberOfRowsInSection is returning [array count];? Is there a preferred way to fix this?

War es hilfreich?

Lösung

Hard to say on the limited info provided, but it's hard to reconcile point 5, that your array is reinitialized, but that your db request is still in progress. If the model object that backs the table is reset, the database query shouldn't still be running. Either:

  • you should have canceled the asynchronous data request once the model object went out of scope (e.g. use operation queue, which if the operations are designed property, are cancelable, instead of GCD); or

  • you should persist that model object in some cache mechanism, so that as the asynchronous data request is completed, when you come back to the controller in step 4, you already have the data cached and ready for display.

In terms of other potential sources of issues, I wonder if your asynchronous data update process is truly thread-safe. Are you synchronizing your interaction with those properties that you're updating asynchronously? This synchronization is generally done via some locking mechanism or via a dedicated serial queue (or using concurrent queue in reader/writer pattern). Thread-safety is a non-trivial issue and I wonder how confident you are on that score.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top