2013-07-12 111 views
4

我有一个循环函数,并在其中调用[NSThread sleepForTimeInterval:2.0] ;.这意味着在2s之后,循环函数被调用。我想在传递新视图时,此循环函数停止,返回时再次调用。使用[NSThread sleepForTimeInterval:2.0]时是否可以停止或取消循环功能;在IOS

我用这个代码来调用循环功能:

-(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]; 

} 

和循环功能:

-(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; 
    } 

} 

而且viewdisappear()

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

我的问题是,当通过新的观点, updateArray仍然会调用。它不会停止。你有什么建议吗?

回答

2

您可以使用键值观察器来尝试它。您可以在以下方法中实施更改,这些更改将随特定值的更改而自动调用。首先,您必须为即将更改的伊娃尔设置通知。

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

然后,你必须实现以下方法修改为按规定:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
0

有几个问题,在我扑过来:

  1. 如果您意图是实际取消sleepForTimeInterval,我不相信你能做到这一点。还有其他的机制(比如定时器)更适合这个问题。

  2. 另外,您每两秒发出一次异步请求。但是,您无法保证您之前的请求会在该段时间内完成。因此,最终可能会有多个网络请求积压,这些请求会在视图解除后继续运行。

    我原以为你会想要启动“等待两秒钟”里面你的异步请求的完成块,以确保你的请求不会在你的“每两秒钟”逻辑后面积压。很明显,除非您使请求同步,否则显然这不适用于当前的while循环,因此您可能会重构此代码,用执行单个请求的内容替换while循环,并且在完成块中等待两秒钟,然后再启动下一个请求。

  3. 您正在检查loop的状态,等待两秒钟,然后发出您的请求。因此,如果视图在执行两秒钟的睡眠时消失,那么在您完成睡眠之后,没有任何事会阻止请求被发出。

    最起码,如果你要使用sleepForTimeInterval,您大概想你睡完检查后loop状态。但是,我的第一点是,最好使用一些可取消的机制,例如计时器。

  4. 如果你说你的循环永远不会退出,我建议你检查一下,确保外观方法像你认为的那样被调用。

就个人而言,我倾向于用它可以很容易地被取消计时器/无效做到这一点:

  1. 定义我的属性:

    @property (nonatomic, strong) NSTimer *timer; 
    @property (nonatomic, getter = isLooping) BOOL looping; 
    @property (nonatomic, weak) AFHTTPRequestOperation *operation; 
    
  2. 有我的样子方法设置looping变量并根据需要启动/停止计划的请求:

    - (void)viewDidAppear:(BOOL)animated 
    { 
        self.looping = YES; 
        [self scheduleRequestIfLooping]; 
    } 
    
    - (void)viewWillDisappear:(BOOL)animated 
    { 
        self.looping = NO; 
        [self cancelScheduledRequest]; 
    } 
    
  3. 是做调度的请求的启动和停止,将使用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]; 
    } 
    

    注意,cancel方法是否应该取消定时器和正在进行中的任何电流要求(如果有的话)你决定。

  4. 最后,把当前请求的完成块内的下一个请求的调度放在内。

    - (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 
    } 
    

在上面,我使用定时器的主线程。如果你真的想在后台队列上完成,你可以,但(a)由于网络请求已经发生在后台线程上,所以对我来说似乎没有必要;和(b)如果你在后台线程上执行此操作,则可能需要确保对状态变量等进行必要的线程安全处理。这对我来说似乎是一种不必要的复杂。