什么可能导致此代码不允许重新进入跳板?

时间:2012-06-28 23:21:14

标签: ios multithreading asynchronous nsurlconnection nsoperation

我有一个应用程序可以同时将图像上传到一堆地方,有点像Instagram风格。

使用NSOperationQueue进行设置,在异步NSOperation周围运行一堆NSURLConnection个包装器。

大多数问题都是这样开始的“回调不会被调用,因为调用线程在它们返回之前已经连接。这是那样的问题。我 am < / em>按预期收到我的回调,但是当按下主页按钮时,我也会以某种方式阻止应用程序进行后台处理。我一直认为由于沙盒而无法阻止它,但不知怎的,我已经完成了它。操作正在运行时的主页按钮在完成之前不会执行任何操作,此时(​​20-30秒后)应用程序将正确显示背景。

** NB这似乎只发生在单核处理器设备上。我只能在我的iPhone 4上重现,但不能在我的4S或iPad 3上重现。*

还有兴趣吗?这是我的设置:

self.uploadQueue = [[NSOperationQueue alloc] init];
[self.uploadQueue setMaxConcurrentOperationCount:1];
[self.uploadQueue setSuspended:YES];

稍后,我将操作添加到队列中,然后将其取消挂起以启动。以下是NSOperation子类的一些代码:

- (BOOL)isConcurrent { return YES; }
- (BOOL)isExecuting { return self.executing; }
- (BOOL)isFinished { return self.finished; }

- (void)start {
    // Omitted: check for cancel...
    // Omitted: check if setup to run

    [self willChangeValueForKey:@"isExecuting"];
    self.executing = YES;
    [self didChangeValueForKey:@"isExecuting"];

    [self.sharer share];    
    CFRunLoopRun();
}


- (void)completeOperation {
    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];
    self.executing = NO;
    self.finished = YES;
    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
    CFRunLoopStop(CFRunLoopGetCurrent());
}

share方法设置异步NSURLConnection并将其关闭,如下所示:

- (void)share {
    // Omitted: connection setup
    [NSURLConnection sendAsynchronousRequest:postRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *error){
        // handle error or success, then call
        [self.currentOperation completeOperation];
    }];

除了我试图解决的副作用之外,代码工作,因为它完成了它应该做的事情,回调被调用,线程保持活着,只要它们需要to,并且操作队列一次只运行指定数量的操作。

我尝试了什么?我试过了:

  1. [NSOperationQueue currentQueue]上调用NSURLConnection。这导致异步连接不回调块。
  2. start方法中强制每个NSOperation到主线程。这并没有解决问题,也导致代码有时无法工作,UI有时会冻结。
  3. 使用可变数组和GCD实现我自己的队列以获得正确的分派线程。无法让它发挥作用。
  4. 操作中的同步NSURLConnection。我没有真正尝试这个,因为它不适合我。某些网络框架(如Facebook iOS SDK)没有同步选项。
  5. 在按下主页按钮之后暂停执行,但在操作完成之前不会产生任何有趣的事情。主线程上似乎没有任何东西等待锁定或执行完成。

    Threads 1 Threads 2

    我是否将其设置为完整的bozo?这里发生了什么,我该如何解决?

1 个答案:

答案 0 :(得分:0)

编辑:

原来所有这些网络东西都是红鲱鱼。这是一些循环的CAAnimations阻止以某种方式返回跳板。

原始猜测:

我的猜测:您不应该在启动方法中调用CFRunLoopRun;期望并发操作的start方法在操作完成之前返回并在稍后完成。你可能正在坚持一些系统需要调度其他任务的GCD锁(线程?)。

如果您需要通过CFRunLoopRun独占线程,您应该在start中启动自己的线程,然后返回。我认为这样做会更容易,只是不使用NSOperation并从主线程中启动你的(已经是异步的)url连接,在每个连接完成时保留一组内容。

实际上,我认为问题是CFRunLoopStop(CFRunLoopGetCurrent()):你在主线程上运行它,所以你要停止主运行循环!