2011-11-29 58 views
1

我试图对UIAlertView进行子类化,以更好地处理我的应用中的错误状态。麻烦时遇到与otherButtonTitles无终止的参数,当我创建我的子类,它只是拿起在列表中的第一个字符串,而不是所有的字符串UIAlertView的子类化

+ (ErrorAlertView *)displayErrorAlertViewWithTitle:(NSString *)title 
              message:(NSString *)message 
              delegate:(id<UIAlertViewDelegate>)delegate 
            errorDelegate:(id<ErrorAlertViewDelegate>)errorDelegate 
           cancelButtonTitle:(NSString *)cancelButtonTitle 
             displayNow:(BOOL)displayNow 
               tag:(NSUInteger)tag 
           otherButtonTitles:(NSString *)otherButtonTitles, ...; 

{ 

    ErrorAlertView *errorAlertView = [[ErrorAlertView alloc] initWithTitle:title 
                    message:message 
                   delegate:delegate 
                 cancelButtonTitle:cancelButtonTitle 
                 otherButtonTitles:otherButtonTitles, nil]; 


    errorAlertView.errorDelegate = errorDelegate; 
    errorAlertView.tag = tag; 

    if (displayNow) { 

    [errorAlertView show]; 

    } 

    return [errorAlertView autorelease]; 


} 

如果我提出以下拨打以上方法:

[ErrorAlertView displayErrorAlertViewWithTitle:[self noInternetConnectionAlertViewTitle] 
              message:[self noInternetConnectionAlertViewMessage] 
              delegate:self 
            errorDelegate:errorDelegate 
           cancelButtonTitle:@"OK" 
             displayNow:YES 
               tag:ErrorAlertTagInternetConnectionError 
           @"Try again",@"Setting", nil]; 

显示的UIAlertView只显示@“Try again”按钮。

+1

[目的-C绕过...零终止参数列表(可能重复http://stackoverflow.com/questions/2345196/objective-c-passing-around-nil-终止参数列表) –

回答

4

您不能发送一组变量参数。

当我子类UIAlertView中我这样做:

va_list args; 
va_start(args, otherButtonTitles); 
for (NSString *anOtherButtonTitle = otherButtonTitles; anOtherButtonTitle != nil; anOtherButtonTitle = va_arg(args, NSString*)) { 
    [self addButtonWithTitle:anOtherButtonTitle]; 
} 

或者,你可以创建你的函数的一个变种,它接受的va_list的(单)参数,然后运行上面的代码。

一般来说,在编写可变参数函数时,应该包含处理这种可能性的替代方法。在这种情况下,Apple提供addButtonWithTitle:方法。

+1

谢谢,完美的作品 – williamb

14

UIAlertView Class Reference

子类票据

的UIAlertView中类旨在被原样使用,并且不支持 子类。该类的视图层次结构是私有的,并且不得修改 。

但是,还有许多其他警报视图实现,您可能会发现有用,发布here on CocoaControls

+2

它可以由于各种原因而安全地进行分类,例如创建自动解雇时进入后台状态版本。 – tarmes

+3

从随机观察中推断出,如果Apple文档*明确指出某些东西不会被子类化,那么子类就是安全的,这是一个非常糟糕的主意。他们可能有内部缓存或使用其他技术,以微妙的方式破坏或损坏记忆。即使它现在起作用,苹果公司可能会稍后改变课程,因为毕竟它被记录为非子类。开发者可能会保留这一点,直到有时间实现特定的新功能或优化或错误修复。 – uliwitness

+1

@Suragch更新,谢谢。 – Luke

1

而不是UIAlertView的子类,我更喜欢创建简单的类,通常只有一个show方法需要一个委托参数。委托协议则具有与可用选项相对应的表达方法。

虽然这种方法导致比典型的警报视图委托方法更多的委托功能,但我认为它使代码更具可读性。

的代码通常看起来像这样(SWIFT):

@objc protocol DeleteUniverseAlertViewDelegate { 
    func deleteUniverseAlertViewDidConfirmDelete(view: DeleteUniverseAlertView) 
} 


class DeleteUniverseAlertView : NSObject, UIAlertViewDelegate { 

    private weak var delegate: DeleteUniverseAlertViewDelegate? = nil 

    class func showWithDelegate(delegate: DeleteUniverseAlertViewDelegate) -> DeleteUniverseAlertView { 
     let view = DeleteUniverseAlertView() 
     view.delegate = delegate 
     UIAlertView(title: "Delete universe?", message: "Are you really, really sure about this?", delegate: view, cancelButtonTitle: "Cancel", otherButtonTitles: "Yes, delete!").show() 
     return view 
    } 

    func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) { 
     if (buttonIndex > 0) { 
      delegate?.deleteUniverseAlertViewDidConfirmDelete(self) 
     } 
    } 
} 

当你再需要出示此警报,只实现了协议,并显示类似这样的定制警报(记得要保持一个强大的参考警报视图):

deleteAlert = DeletePlaceAlertView.showWithDelegate(self)