【问题标题】:How to disable button in UIActionSheet?如何禁用 UIActionSheet 中的按钮?
【发布时间】:2009-07-22 05:57:48
【问题描述】:

我需要禁用 UIActionSheet 中的按钮。经过一些操作后,我需要再次启用它们。那么有没有办法做到这一点。

谢谢

【问题讨论】:

    标签: iphone


    【解决方案1】:

    基于多个线程,我将答案汇总到 UIActionSheet 上的一个类别中,并添加了一个 setButton:toState 方法,如下所示。 希望对您有所帮助:

    @interface UIActionSheet(ButtonState)
    - (void)setButton:(NSInteger)buttonIndex toState:(BOOL)enbaled;
    @end
    
    @implementation UIActionSheet(ButtonState)
    - (void)setButton:(NSInteger)buttonIndex toState:(BOOL)enabled {
        for (UIView* view in self.subviews)
        {
            if ([view isKindOfClass:[UIButton class]])
            {
                if (buttonIndex == 0) {
                    if ([view respondsToSelector:@selector(setEnabled:)])
                    {
                        UIButton* button = (UIButton*)view;
                        button.enabled = enabled;
                    }
                }
                buttonIndex--;
            }
        }
    }
    @end
    

    【讨论】:

    • 很好的解决方案,非常简单,易于使用并且以正确的工程方式完成。 +1
    【解决方案2】:

    Swift 3.0 版本:

    let actionSheet = UIAlertController(title:nil, message:nil, preferredStyle:UIAlertControllerStyle.actionSheet)
    
    
    actionSheet.addAction(UIAlertAction(title:"Modify", style:UIAlertActionStyle.default, handler:{ action in
        // Do your thing here
    }))
    
    let disabledDelete = UIAlertAction(title:"Cannot delete this item", style:UIAlertActionStyle.destructive, handler:nil)
    disabledDelete.isEnabled = false
    actionSheet.addAction(disabledDelete)
    
    actionSheet.addAction(UIAlertAction(title:"Cancel", style:UIAlertActionStyle.cancel, handler:nil))
    
    self.present(actionSheet, animated:true, completion:nil)
    

    【讨论】:

      【解决方案3】:

      稍微改进了 Reuven 的版本 [唉,我不能给他添加评论,因为我还没有“声誉”……]。

      @interface UIActionSheet (ButtonEnabled)
      - (void)setButtonAtIndex:(NSUInteger)index Enabled:(BOOL)enabled;
      @end
      
      @implementation UIActionSheet (ButtonEnabled)
      - (void)setButtonAtIndex:(NSUInteger)index Enabled:(BOOL)enabled
      {
          for (UIView* view in self.subviews) {
              if ([view isKindOfClass:[UIButton class]]) {
                  if (index-- == 0) {
                      [(UIButton*)view setEnabled:enabled];
                      break;
                  }
              }
          }
      }
      @end
      

      前面的 respondsToSelector: 检查是多余的,因为我们已经在检查 UIButton(这是一个 UIControl 子类,都支持 setEnabled)。为了与 Apple 的 NSArrays 保持一致,我也更改为“AtIndex”和 NSUInteger,但这主要是化妆品。

      整体方法似乎工作正常,但请注意,它确实假设按钮子视图的顺序与构建操作表时按钮索引的顺序精确匹配,这在任何 AFAIK 中都没有严格记录。

      【讨论】:

      • 顺便说一句,根据this,当您的操作表中有太多项目时,按钮索引确实会出现问题。所以如果你有很多的话,这会搞砸这种方法(用于禁用)。
      【解决方案4】:

      所提供的解决方案不适用于 iOS 8。如果有人没有为此使用 UIAlertController(这是 Apple 推荐的做法),这就是我修改 @Reuven 的答案以使其也适用于 iOS 8 的方式:

      (第二阶段基于this所以回答)

      - (void)setButton:(NSInteger)buttonIndex toState:(BOOL)enabled {
      
          SEL selector = NSSelectorFromString(@"_alertController");
      
          //iOS 8
          if ([self respondsToSelector:selector]) {
      
              UIAlertController *alertController = [self valueForKey:@"_alertController"];
      
              if ([alertController isKindOfClass:[UIAlertController class]]){
      
                  UIAlertAction *action = alertController.actions[buttonIndex];
      
                  [action setEnabled:enabled];
      
              }
      
          //iOS 7
          }else{
      
              for (UIView* view in self.subviews){
      
                  if ([view isMemberOfClass:NSClassFromString(@"UIAlertButton")]) {
      
                      if (buttonIndex == 0) {
      
                          if ([view respondsToSelector:@selector(setEnabled:)]){
      
                              UIButton* button = (UIButton*)view;
      
                              button.enabled = enabled;
      
                          }
      
                      }
      
                      buttonIndex--;
      
                  }
      
              }
      
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        这可能有点晚了。但是,我想出的方法是创建 UIButton(s) 并添加它们 到 UIActionSheet 子视图。确保将这些按钮放在顶部并完全覆盖要替换的默认 UIActionSheet 按钮。当 UIButton 放置在默认的 UIActionSheet 按钮上时,它的 UIResponder 优先于 UIActionSheet 按钮 UIResponder。因此,这样做您可以禁用和启用这些按钮,但是您希望在 UIViewController 逻辑中的任何位置。这可能是访问 SDK 的私有方法(如上 - UIThreePartButton)的替代方法,并且苹果可能会拒绝您的应用程序。我相信这符合 Apple 准则。

        // Instantiate once
        if (self.actionSheet==nil)  {
            UIActionSheet *as = [[UIActionSheet alloc] 
                                 initWithTitle:@""
                                 delegate:self 
                                 cancelButtonTitle:@"Cancel"
                                 destructiveButtonTitle:@"Load Data"
                                 otherButtonTitles:@"Update Data",nil];
        
            //[actionSheet showInView:self.view];
            self.loadUIButton.frame = CGRectMake(24.0f,25.0f,275.f,46.0f);
            [as addSubview: self.loadUIButton];
            self.updateUIButton.frame = CGRectMake(24.0f,78.0f,275.f,46.0f);
            [as addSubview: self.updateUIButton];
            //[actionSheet addSubview: self.cancelUIButton];
            //[as showFromToolbar: self.navigationController.toolbar];
            self.actionSheet = as;
            [as release];
        }
        [self.actionSheet showFromToolbar: self.navigationController.toolbar];
        

        【讨论】:

          【解决方案6】:

          这些按钮是 UIActionSheet 的子视图,它们的类是 UIThreePartButton

          你可以得到它们并做你想做的一切:

          UIActionSheet *a = [[UIActionSheet alloc]initWithTitle:@"" delegate: nil cancelButtonTitle: @"c" destructiveButtonTitle: @"d" otherButtonTitles: @"ot", nil];
              [a showInView: window];
          
              for(UIView *v in [a subviews])
              {
                  if([[v description] hasPrefix: @"<UIThreePartButton"] )
                  {
                      v.hidden = YES;  //hide
                     //((UIButton*)v).enabled = NO;   // disable
          
                  }
              }
          

          【讨论】:

          • 我建议你不要使用这种方法,因为这些是 SDK 私有的。 Apple 可能会拒绝您的应用。最好的选择是根本不显示这些按钮,而是禁用它们
          • 这段代码中没有私有方法)) 只有公共:) 有时我在我的应用程序中使用私有方法。我在应用程序中使用了两次,苹果没有拒绝这些应用程序
          • 这不仅仅是被 Apple 拒绝,使用私有 API 还表明对您的客户缺乏尊重。私有 API 是私有的,因为 Apple 仍在锁定它们,所以如果它们发生变化,你的应用程序就会崩溃。如上所述的视图遍历导致许多应用程序在 3.0 下崩溃,以至于 Apple 在发行说明中指出了这一点,并表示不要这样做。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-11
          • 1970-01-01
          • 2011-01-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多