zbMax
zbMax

Reputation: 2818

Delay a call to a class method

I have a class which contains only class methods. Typically, I use these methods to refresh data for my app.
This way, for example, I want a TableViewController to trigged methods from the first class mentioned regularly.
What I also need is the possibility to stop these calls when my TableViewController is not shown anymore.

What I'm doing now is probably not the best thing to do :

//myNetworkingClass.h
 +(void)methods1:(type*)param1;

     ---
//myNetworkingClass.m

+(void)methods1:(type*)param1
{
    //asynchronous tasks
    [[NSNotificationCenter defaultCenter] postNotificationName:@"updateComplete" object:responseObject];
}

 //myTableViewController.m
  - (void)viewDidLoad
 {
     //initialization
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateReceived:) name:@"updateComplete" object:nil];
    [myNetworkingClass methods1:param];
}
-(void)updateReceived:(NSNotification*)notification
{
    //some task, especially update datasource
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 10* NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [myNetworkingClass methods1:param];
    });
}

There is 3 problems using this :

How should I deal with these constraints and write a "neat coed" :p

Thanks for your help.

EDIT

With the link of @AdamG, I've created a NSOperation :

@interface OperationRefresh : NSOperation
-(id)initWithArray:(NSArray *)array andDelay:(int)refreshTime;
@end

@implementation OperationRefresh
{
    NSArray *paramA;
    int delay;
}
-(id)initWithArray:(NSArray *)array andDelay:(int)refreshTime
{
    self = [super init];
    paramA = array;
    delay = refreshTime;
    return self;
}
-(void)main
{
    @autoreleasepool {
        NSLog(@"sleeping...");
        [NSThread sleepForTimeInterval:delay];
        NSLog(@"Now Refresh");
        [myNetworkingClass methods1:paramA];
    }
}
@end

But I'm not able to cancel it. Here is what I'm doing :

-(void)updateReceived:(NSNotification*)notification
{
    //some task, especially update datasource
    refreshOperation = [[OperationRefresh alloc] initWithArray:param andDelay:10];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
        [refreshOperation start];
    });
}


-(void)viewWillDisappear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [refreshOperation cancel];
}

Indeed, when my view disappears, it still writing "Now Refresh" in the console.

Upvotes: 0

Views: 191

Answers (1)

AdamG
AdamG

Reputation: 3718

You should be using NSOperations, which will allow you to cancel your operation that is running in the background.

There is a great tutorial here: http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues.

It's also much more efficient and will keep your app from lagging due to background tasks.

UPDATE

To cancel you have to manually add a cancellation in the NSOperation. You should add this wherever you might want the operation to be canceled (probably before and after the delay).

if (self.isCancelled){
   // any cleanup you need to do
   return;
}

Upvotes: 2

Related Questions