1

我正在使用一个块来执行与网络相关的任务

当我的块完成时UITableViewController,我想重新加载 tableviewcontroller

__unsafe_unretained UITableView *unretTableView = self.tableview;

[myRequest postWithCompletion:(bool finished) {
    [unretTableView reloadData];
}];

这很好,除了如果我在请求完成之前离开(deallocate),UITableViewController我似乎指向一个已释放对象(unretTableView消息发送到已释放实例,即使在[UITableViewController dealloc]我设置的方法(正在调用)中self.tableview = nil;

额外细节:

  • 无法使用__weak,我的目标是 iOS 4.3 及更高版本
  • UITableViewController'sdealloc方法中,我设置self.tableview = nil
  • 我不想在您离开页面时取消网络请求,我希望它继续运行。
  • 编辑:我也不想在块中保留 self.tableview

谢谢!

4

4 回答 4

1

鉴于您的评论,我可能倾向于追求NSOperationQueue. 这样你就可以

  1. 创建背景NSOperationQueue

  2. 如果您的下载允许某个合理数量的同时下载,您可以设置maxOperationCount(或者如果您想要连续下载,请将其设置为 1)。

  3. 当您启动后台作业时,您可以创建NSOperation对象,或者直接NSOperationQueue通过addOperationWithBlock. 如果您想享受检查isCancelled标志的能力,您可能需要执行前者。

  4. 每个操作都可以在尝试更新视图控制器之前检查它是否被取消。

  5. 当视图控制器被关闭时,它可以执行一个简单cancelAllOperations的取消所有排队的操作。

这是一个随机的例子:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.queue = [[NSOperationQueue alloc] init];
    self.queue.maxConcurrentOperationCount = 4;

    // let's add 100 operations to our queue

    for (NSInteger i = 0; i < 100; i++)
    {
        NSBlockOperation *operation = [[NSBlockOperation alloc] init];
        __unsafe_unretained NSBlockOperation *weakOperation = operation; // it seems vaguely disturbing to do this with __unsafe_unretained, but given that the operation queue is taking care of this for us, I believe it's ok
        [operation addExecutionBlock:^{

            NSLog(@"Beginning operation %d", i);

            sleep(10);

            if ([weakOperation isCancelled])
                NSLog(@"Operation cancelled %d", i);
            else
            {
                // go ahead and update UI if you want
                NSLog(@"Finished operation %d", i);
            }
        }];

        [self.queue addOperation:operation];
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    [self.queue cancelAllOperations];
}
于 2012-12-10T22:19:55.543 回答
0

您稍后设置的属性与块捕获的变量设置的内容无关。如果要访问该属性,则需要访问该属性:self.foo,而不是 foo。

请注意,在这种情况下您仍然必须小心,因为在块中捕获 self 会导致 self 被保留,这可能会导致保留循环。

(编辑)如果您从另一个线程更新属性,这仍然不安全。您需要某种形式的序列化结构来确保安全(NSLock、NSOperationQueue、dispatch_queue_t 等...)。我假设这不是线程化的,但以防万一,这很重要。

于 2012-12-10T21:39:56.563 回答
-1

尝试这个:

__block __unsafe_unretained UITableView *unretTableView = self.tableview;

编辑

我不知道您使用什么框架来发布请求。但是当您使用[myRequest postWithCompletion: yourBlock]发布请求时,我想还有一种方法可以更改完成块,例如myRequest.completion=nil

于 2012-12-10T21:36:46.630 回答
-2

Insert a sanity check.

__weak UITableView *table = unretTableView;
if (table) [unretTableView reloadData];
于 2012-12-10T21:35:10.880 回答