子类化 UIAlertView

Posted

技术标签:

【中文标题】子类化 UIAlertView【英文标题】:Subclassing UIAlertView 【发布时间】:2011-11-29 11:20:10 【问题描述】:

我正在尝试继承 UIAlertView 以更好地处理我的应用程序中的错误状态。遇到的问题是 otherButtonTitles nil 终止参数,当我创建我的子类时,它只拾取列表中的第一个字符串而不是所有字符串

+ (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 仅显示@“再试一次”按钮。

【问题讨论】:

Objective-C passing around ... nil terminated argument lists 的可能重复项 【参考方案1】:

来自UIAlertView Class Reference

子类化注释

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

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

【讨论】:

可以出于各种原因安全地对其进行子类化,例如创建一个在进入背景状态时自动关闭的版本。 如果 Apple 文档明确声明某些东西不能被子类化,那么从随机观察中推断出某些东西是安全的子类化是一个非常糟糕的主意。它们可能具有内部缓存或使用其他技术会以微妙的方式破坏或破坏内存。即使它现在可以工作,Apple 也可能会在以后更改该类以中断,因为毕竟它被记录为不可子类化。开发人员可能会保留此功能,直到有时间实施特定的新功能或优化或错误修复。【参考方案2】:

你不能像那样发送一组可变的参数。

当我继承 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: 方法。

【讨论】:

【参考方案3】:

我更喜欢创建简单的类,而不是子类化 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)

【讨论】:

以上是关于子类化 UIAlertView的主要内容,如果未能解决你的问题,请参考以下文章

CAsyncSocket 没有子类化?

子类化导航控制器有啥用? [关闭]

麻烦子类化 SCNScene

UIViewController 的 Swift 子类化子类

子类化 UIAlertController

子类化 UItableViewCell 选择