如何在UIActionSheet中禁用按钮?

时间:2022-11-19 15:54:04

I need to disable the buttons in UIActionSheet. after some operations i need to enable them again. So is there a way to do this.

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

Thanks

6 个解决方案

#1


-2  

Thees buttons are subviews of UIActionSheet and their class is UIThreePartButton

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

You can get them and do all that you want:

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

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

        }
    }

#2


17  

Based on a number of thread, i've aggregated an answer into a category on UIActionSheet, adding a setButton:toState method as follows. Hope it helps:

基于一些线程,我在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

#3


2  

Slightly improved version of Reuven's [alas I cant add a comment to his 'cause I dont have the 'reputation' yet...].

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

The previous respondsToSelector: check was extraneous, because we are already checking for UIButton (which is a UIControl subclass, which all support setEnabled]. In keeping with Apple's NSArrays, I also changed to "AtIndex" and NSUInteger, but that's mostly cosmetic.

之前的respondsToSelector:check是无关紧要的,因为我们已经在检查UIButton(这是一个UIControl子类,它都支持setEnabled)。为了与Apple的NSArrays保持一致,我也改为“AtIndex”和NSUInteger,但这主要是装饰性的。

The overall approach seems to work fine, but please note it does assume the order of the button subviews precisely matches the order of the button indexes when the action sheet was constructed, which isn't strictly documented anywhere AFAIK.

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

#4


2  

Swift 3.0 version:

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)

#5


1  

The provided solutions do not work on iOS 8. In case anyone is not using the UIAlertController for this (which is Apple's recommended way of doing it) this is how I modified @Reuven's answer to work for iOS 8 too:

提供的解决方案在iOS 8上不起作用。如果有人没有使用UIAlertController(这是Apple推荐的方式),这就是我修改@ Reuven对iOS 8工作的答案:

(the second phase is based on this so answer)

(第二阶段基于此答案)

- (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--;

            }

        }

    }

}

#6


0  

This is probably a bit late. But, the way I figured out is create UIButton(s) and add them to UIActionSheet subview. Make certain these buttons are placed on top and completely cover the default UIActionSheet button(s) to replace. When the UIButton is placed over the default UIActionSheet button, its UIResponder takes precedence over UIActionSheet button UIResponder. So, doing so you can disable and enable those buttons however you'd like anywhere in you UIViewController logic. This may be an alternative to accessing private methods to the SDK (like above - UIThreePartButton) and apple might reject your app. I believe this follows the Apple guidelines.

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

i.e.

// 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];

#1


-2  

Thees buttons are subviews of UIActionSheet and their class is UIThreePartButton

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

You can get them and do all that you want:

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

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

        }
    }

#2


17  

Based on a number of thread, i've aggregated an answer into a category on UIActionSheet, adding a setButton:toState method as follows. Hope it helps:

基于一些线程,我在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

#3


2  

Slightly improved version of Reuven's [alas I cant add a comment to his 'cause I dont have the 'reputation' yet...].

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

The previous respondsToSelector: check was extraneous, because we are already checking for UIButton (which is a UIControl subclass, which all support setEnabled]. In keeping with Apple's NSArrays, I also changed to "AtIndex" and NSUInteger, but that's mostly cosmetic.

之前的respondsToSelector:check是无关紧要的,因为我们已经在检查UIButton(这是一个UIControl子类,它都支持setEnabled)。为了与Apple的NSArrays保持一致,我也改为“AtIndex”和NSUInteger,但这主要是装饰性的。

The overall approach seems to work fine, but please note it does assume the order of the button subviews precisely matches the order of the button indexes when the action sheet was constructed, which isn't strictly documented anywhere AFAIK.

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

#4


2  

Swift 3.0 version:

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)

#5


1  

The provided solutions do not work on iOS 8. In case anyone is not using the UIAlertController for this (which is Apple's recommended way of doing it) this is how I modified @Reuven's answer to work for iOS 8 too:

提供的解决方案在iOS 8上不起作用。如果有人没有使用UIAlertController(这是Apple推荐的方式),这就是我修改@ Reuven对iOS 8工作的答案:

(the second phase is based on this so answer)

(第二阶段基于此答案)

- (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--;

            }

        }

    }

}

#6


0  

This is probably a bit late. But, the way I figured out is create UIButton(s) and add them to UIActionSheet subview. Make certain these buttons are placed on top and completely cover the default UIActionSheet button(s) to replace. When the UIButton is placed over the default UIActionSheet button, its UIResponder takes precedence over UIActionSheet button UIResponder. So, doing so you can disable and enable those buttons however you'd like anywhere in you UIViewController logic. This may be an alternative to accessing private methods to the SDK (like above - UIThreePartButton) and apple might reject your app. I believe this follows the Apple guidelines.

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

i.e.

// 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];