Can I stop or cancel the loop function when using [NSThread sleepForTimeInterval: 2.0]; in iOS

I have a loop function and it calls [NSThread sleepForTimeInterval: 2.0] ;. this means that after 2s the loop function is called. I want this loop function to be stopped on a new view, and when it is back, it is called again.

I use this code to call the loop function:

-(void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; loop = YES; delete=NO; temp = [FileCompletedArray mutableCopy]; NSOperationQueue *queue = [NSOperationQueue new]; operations = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(updateArray) object:nil]; [queue addOperation:operations]; [operations release]; } 

And the loop function:

 -(void)updateArray{ while (loop) { NSLog(@"start loop"); if(loop){ [NSThread sleepForTimeInterval:2.0]; NSLog(@"start send request"); NSURL *url1 = [NSURL URLWithString:@"http://server.com"]; NSMutableURLRequest *afRequest = [httpClient requestWithMethod:@"POST" path:nil parameters:params1] ; operation= [[AFHTTPRequestOperation alloc] initWithRequest:afRequest]; NSLog(@" request sent"); [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Server response1"); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"error: %@", error); } ]; [httpClient enqueueHTTPRequestOperation:operation]; } else return; } } 

And viewdisappear ()

 -(void) viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; loop = NO; delete=NO; [operations cancel] ; } 

My problem is to pass in a new view, updateArray still calls. This does not stop. Do you have any suggestions?

+4
source share
2 answers

You can try it with the help of observers with key values. You can implement the changes in the following method, which will be automatically called as a change to a specific value. You must first set a notification for ivar to be changed.

 [self addObserver:self forKeyPath:@"loop" options:NSKeyValueObservingOptionNew context:nil]; 

Then you need to make the changes as required by the following method:

 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
+2
source

There are a few issues that go to me:

  • If you intend to actually cancel sleepForTimeInterval , I don't think you can do this. There are other mechanisms (such as timers) that are much better suited to this problem.

  • Aside, you issue an asynchronous request every two seconds. But you have no assurance that your previous request will be completed within this period of time. As a result, you may get behind several network requests, which will continue to be executed after the view is rejected.

    I would think that you want to initiate a “wait two seconds” inside the completion block of your asynchronous request, to ensure that your requests are not forgotten behind your logic “every two seconds”. Obviously, this will not work with your current while if you do not make the request synchronous, so you can reorganize this code by replacing the while with one that executes the request, and in the completion block two seconds before the start of the next request.

  • You check the status of the loop , waiting for two seconds, and then issuing your request. Therefore, if the performance disappeared during the execution of the second sleep mode, nothing stops here, after you have finished sleeping, there was nothing.

    At the very least, if you intend to use sleepForTimeInterval , you probably want to check the state of the loop after sleep is complete. But, to my first point, it is better to use some kind of cancellation mechanism, such as a timer.

  • If you say that your loop never exits, I suggest you check to make sure that the appearance methods are invoked the way you think they should be.

Personally, I would be inclined to do this with a timer that can be easily undone / nullify:

  • Define my properties:

     @property (nonatomic, strong) NSTimer *timer; @property (nonatomic, getter = isLooping) BOOL looping; @property (nonatomic, weak) AFHTTPRequestOperation *operation; 
  • Ask my appearance methods to set the looping variable and start / stop scheduled requests:

     - (void)viewDidAppear:(BOOL)animated { self.looping = YES; [self scheduleRequestIfLooping]; } - (void)viewWillDisappear:(BOOL)animated { self.looping = NO; [self cancelScheduledRequest]; } 
  • Methods that start and stop scheduled requests will use NSTimer :

     - (void)scheduleRequestIfLooping { if ([self isLooping]) { self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(initiateRequest:) userInfo:nil repeats:NO]; } } - (void)cancelScheduledRequest { [self.timer invalidate]; self.timer = nil; // you might want to cancel any `AFHTTPRequestOperation` // currently in progress, too [self.operation cancel]; } 

    Note that the cancel method should cancel both the timer and the current current current request (if any).

  • Finally, schedule the next request inside the current request completion block.

     - (void)initiateRequest:(NSTimer *)timer { // create AFHTTPRequestOperation AFHTTPRequestOperation operation = ... // now schedule next request _after_ this one, by initiating that request in the completion block [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Server response1"); [self scheduleRequestIfLooping]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"error: %@", error); // not sure if you want to schedule request if last one failed }]; self.operation = operation; // save this in the property } 

In the above example, I use the main thread for the timer. If you really want to do this in the background, you can, but (a) it seems unnecessary to me, since network requests are already happening in the background thread; and (b) if you do this in the background thread, you might want to make sure that you are doing the necessary thread-safe processing of your state variables and the like. It just seemed to me an unnecessary complication.

0
source

Source: https://habr.com/ru/post/1491069/


All Articles