【问题标题】:UIAlertView's delegate deallocating before it is dismissedUIAlertView 的委托在解除之前解除分配
【发布时间】:2013-08-12 13:06:33
【问题描述】:

在我的应用程序中,我有一个单独的对象来处理身份验证和从网络服务获取我的应用程序需要的信息以填充表格,我们称之为 Getter。

所以首先我的 View Controller 我分配 getter

Getter *get = [[Getter alloc]init];
[get getInfoWithCompletion^(id result) {
    if ([result isKindOfClass:[NSMutableArray class]]) {
        NSMutableArray *array = result;
        self.infoarray = array;
        self.tableView.scrollEnabled = TRUE;
        [self.tableView reloadData];
    }
}];

当 Getter 被告知 getinfo 时,它会分配一个 Downloader 对象,告诉它使用 url 下载并给它一个完成块。当下载器完成时,它会调用一个完成块。

Getter.m

- (void)getInfoWithCompletion:(void (^)(id result))completionBlock{
     self.completion = completionBlock;
     Downloader *download = [[Downloader alloc]init];
     [downloader downloadWithURL:@"http://....." completion:^(id results, NSError *error){
            if (error) {
                [self handleErrorWithError:error];
            } else {
                ....
                self.completion(theResult);
            }
     }];

- (void)handleErrorWithError:(NSError *)error {
     UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error" message:error.localizedDescription delegate:self cancelButtonTitle:@"Skip" otherButtonTitles:@"Retry",nil];
    [alert show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([[alertView buttonTitleAtIndex:buttonIndex]isEqualToString:@"Retry"]) {
    [self getInfoWithCompletion:self.completion];
} else {
    self.completion(nil);
}

这里的问题是,在显示警报视图后,Getter 被释放,所以当警报试图告诉代理点击哪个按钮时,它会崩溃。在 ARC 之前,您可以在委托方法中的警报和 [self release] 之​​前执行 [self retain]。但我不能用 ARC 做到这一点。或者,我可以调用 self.completion(error) 并让视图控制器处理它,但是让 Getter 处理它更可重用,因此我不必每次使用它时都复制错误处理代码。由于我无法使用 ARC 手动保留,我如何确保 Getter 在显示警报视图后保持活动状态?

【问题讨论】:

    标签: ios objective-c cocoa-touch automatic-ref-counting uialertview


    【解决方案1】:

    您应该使 Getter 成为类的属性,并隐含地成为实例变量。

    【讨论】:

      【解决方案2】:

      在 ARC 中,retain 的等效项是将实例存储到 strong 属性中。这可以是显式的,也可以通过将其添加到数组中(如UIViewController 类的childViewControllers)。这样做将使实例保持活动状态,直到您将属性设为 nil 或从数组中删除实例。

      【讨论】:

        【解决方案3】:

        别忘了,块是在堆栈上分配的,所以它们会随着创建它们的上下文消失。如果您复制一个块,则该副本被放置在堆中,因此它可以在创建块的代码返回后继续存在。我不确定在 View Controller 中分配的块的生命周期是多少,但如果需要,您可以保持这种方式:

        self.completion = [completionBlock copy];

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-20
          • 1970-01-01
          • 2013-10-09
          • 2020-07-29
          • 1970-01-01
          相关资源
          最近更新 更多