Andrei Nagy
Andrei Nagy

Reputation: 507

What is a nice way to queue calls for refreshing data?

I've gotten in a few cases when something receives multiple refresh calls in quick succession, eg: - ViewController receives multiple KVO notifications. - Datamanger class that is called from setters to refresh when multiple settings change.

Ideally I would like to execute only the last refresh call from a series (drop all the intermediate ones).

Right now I'm using an isRefreshing property and a needRefresh to block excessive refreshes, eg:

- (id)init {
    ...
    [self observeValueForKeyPath:@"isRefreshing" ....];
}

- (void)setParameter:(NSInteger)parameter {
    ....
    [self refresh];
}
/* and many more kinds of updates require a refresh */
- (void)setAnotherProperty:(NSArray*)array {
    ....
    [self refresh];
}

- (void)refresh {
    if (self.isRefreshing) {
        self.needRefresh = YES;
        return;
   }
   self.isRefreshing = YES;
   ...
   self.isRefreshing = NO;
}

- observeValueForKeyPath..... {
    if (!self.isRefreshing && self.needsRefresh) {
         self.needsRefresh = NO;
         [self refresh];
    }
}

Is there a better solution for this kind of problem?

Upvotes: 1

Views: 68

Answers (2)

Flop
Flop

Reputation: 153

Looks like you should delay refreshing for a while. You can use different techniques to do so. It is enough only one flag. For example you may use async block to make a delay for a one main run-loop cycle

- (void)setParameter:(NSInteger)parameter {
    ....
    [self requestRefrhesh];
}
- (void)setAnotherProperty:(NSArray*)array {
    ....
    [self requestRefrhesh];
}

...

-(void) requestRefrhesh {
    if (self.refreshRequested) {
        return;
    } else {
        self.refreshRequested = YES;    
        dispatch_async(dispatch_get_main_queue(), ^(void){
            //Run in main UI thread
            //make your UI changes here
            self.refreshRequested = NO;
        });
    }
}

Upvotes: 0

Phillip Mills
Phillip Mills

Reputation: 31016

You can create a NSOperationQueue with concurrency set to one and only submit a new operation to it when its operation count is zero. (Or use cancellation logic to remove pending jobs so that only one new one is queued if there's a job in progress.)

What you're doing is reasonable for a single-threaded system but would become fairly complicated for multiple threads.

Upvotes: 1

Related Questions