iOS多个UIAlertView类问题处理---读书笔记

开发 iOS 时经常用到 UIAlertView 类,该类提供了一种标准视图,可向用户展示警告信息。当用户按下按钮关闭该视图时,需要用委托协议(delegate protocol)来处理此动作,但 是,要想设置好这个委托机制,就得把创建警告视图和处理按钮动作的代码分开。由于代码 分作两块,所以读起来有点乱。比方说,我们在使用 UIAlertView 时,一般都会这么写: 

- (void)askUserAQuestion {
    UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:@"Question"
                          message:@"What do you want to do?"
                          delegate:self
                          cancelButtonTitle:@"Cancel"
                          otherButtonTitles:@"Continue", nil];
    [alert show];
}

  

// UIAlertViewDelegate protocol method
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0) {
        [self doCancel];
    }
    else {
        [self doContinue];
    }
}

  

如果想在同一个类里处理多个警告信息视图,那么代码就会变得更为复杂,我们必须在 delegate 方法中检查传入的 alertView 参数,并据此选用相应的逻辑。要是能在创建警告视图 的时候直接把处理每个按钮的逻辑都写好,那就简单多了。这可以通过关联对象来做。创建 完警告视图之后,设定一个与之关联的“块”(block) , 等到执行 delegate 方法时再将其读出 来。此方案的实现代码如下: 

-(void)askUserAQuestion{
    UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:@"第一个Question" message:@"What do you want to do?"
                          delegate:self cancelButtonTitle:@"Cancel"
                          otherButtonTitles:@"Continue", nil];
    
    void(^block)(NSInteger) = ^(NSInteger buttonIndex){
        if (buttonIndex == 0) {
            NSLog(@"00000");
        }else{
            NSLog(@"111111");
        }
    };
    
    objc_setAssociatedObject(alert,
                             EOCMyAlertViewKey,
                             block,
                             OBJC_ASSOCIATION_COPY);
    [alert show];
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    
    void(^block) (NSInteger) = objc_getAssociatedObject(alertView, EOCMyAlertViewKey);
    block(buttonIndex);
    
}

  

以这种方式改写之后,创建警告视图与处理操作结果的代码都放在一起了,这样比原 来更易读懂,因为我们无须在两部分代码之间来回游走,即可明白警告视图的用处。但是, 采用该方案时需注意:块可能要捕获(capture)某些变量,这也许会造成“保留环”(retain cycle)。

正如大家所见,这种做法很有用,但是只应该在其他办法行不通时才去考虑用它。若是 滥用,则很快就会令代码失控,使其难于调试。“保留环”产生的原因很难查明,因为关联对 象之间的关系并没有正式的定义(formal definition),其内存管理语义是在关联的时候才定义 的,而不是在接口中预先定好的。使用这种写法时要小心,不能仅仅因为某处可以用该写法 就一定要用它。想创建这种 UIAlertView 还有个办法,那就是从中继承子类,把块保存为子类 中的属性。若是需要多次用到 alert 视图,那么这种做法比使用关联对象要好。 

原文地址:https://www.cnblogs.com/kw-ios/p/3711663.html