禁用 IBOutletCollection 中的所有子视图

发布于 2024-12-28 16:45:42 字数 1202 浏览 1 评论 0原文

我想禁用/启用 IBOutletCollection 中的所有 UIView。 但是 UIView 的类不同,因此我无法直接调用 setEnabled

然后我想我应该使用performSelector方法来做到这一点,但是我只能发送一个对象作为参数。

我在这个网站和其他网站上都读到我可以只使用 [NSNumber numberWithBool YES/NO],但是当发送带有 bool YES 或 NO 的 NSNumber 时,启用状态不会改变。

我通过使用 nil 使禁用的部分正常工作,但是我找不到将其设置为启用的方法:

-(void) setControlsState: (BOOL) enabled

{
    for(UIView *subview in controls)
    {
        NSNumber *boolObject = enabled? [NSNumber numberWithBool: YES]: nil;
        if([subview respondsToSelector: @selector(setEnabled:)])
        {
            [subview performSelector: @selector(setEnabled:) withObject: boolObject];
        }
        else if([subview respondsToSelector: @selector(setEditable:)])
        {
            [subview performSelector: @selector(setEditable:) withObject: boolObject];
        }
        subview.alpha = enabled? 1: 0.5;
    }
}

其中控件是由 UISliders、UIButtons、UITextViews 和 UITextfields 组成的 IBOutletCollection。 (@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *controls;)

注意: UITextViews 在上面的代码中工作正常,它只是其他类型的 UIViews ,它使用 setEnabled

I want to disable/enable all UIViews in a IBOutletCollection.
However the UIViews differ in class, so I can't call the setEnabled directly.

Then I thought I would use the performSelector method to do it, however I can only send an Object as parameter.

I read both on this site and on other sites that I could just use [NSNumber numberWithBool YES/NO], however the enabled state doesn't change when sending a NSNumber with either bool YES or NO.

I got the disabled part to work by using nil, however I couldn't find a way to set it them enabled:

-(void) setControlsState: (BOOL) enabled

{
    for(UIView *subview in controls)
    {
        NSNumber *boolObject = enabled? [NSNumber numberWithBool: YES]: nil;
        if([subview respondsToSelector: @selector(setEnabled:)])
        {
            [subview performSelector: @selector(setEnabled:) withObject: boolObject];
        }
        else if([subview respondsToSelector: @selector(setEditable:)])
        {
            [subview performSelector: @selector(setEditable:) withObject: boolObject];
        }
        subview.alpha = enabled? 1: 0.5;
    }
}

Where controls is a IBOutletCollection consisting of UISliders, UIButtons, UITextViews and UITextfields. (@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *controls;)

Note: The UITextViews works fine wit the above code, it is only the other type of UIViews, which uses setEnabled.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一身仙ぐ女味 2025-01-04 16:45:42

您不使用不允许触摸事件的 userInteractionEnabled 是否有具体原因?

-(void) setControlsState: (BOOL) enabled
{
    for(UIView *aView in controls)
    {
        if ([aView isKindOfClass:[UIView class]]){
            aView.userInteractionEnabled = enabled;
            aView.alpha = (enabled)?1.0:0.5;// Be mindful of this it doesn't seem to respect group opacity. i.e. sliders look funny.
        }
    }
}

如果有的话,你可以在检查它的类后简单地转换 aView 指针,如下所示:(当然,你必须枚举你使用的所有类)

-(void) setControlsState: (BOOL) enabled
{
    for(UIView *aView in controls)
    {
        if ([aView isKindOfClass:[UISlider class]]){
            [(UISlider *)aView setEnabled:enabled];
        }
        if ([aView isKindOfClass:[UITextView class]]){
            [(UITextView *)aView setEditable:enabled];
        }
        // and so forth
    }
}

Is there a specific reason your not using userInteractionEnabled which disallows touch events?

-(void) setControlsState: (BOOL) enabled
{
    for(UIView *aView in controls)
    {
        if ([aView isKindOfClass:[UIView class]]){
            aView.userInteractionEnabled = enabled;
            aView.alpha = (enabled)?1.0:0.5;// Be mindful of this it doesn't seem to respect group opacity. i.e. sliders look funny.
        }
    }
}

If there is you can simply cast the aView pointer after checking it's class, like so: (Of course you'll have to enumerate through all the classes you use)

-(void) setControlsState: (BOOL) enabled
{
    for(UIView *aView in controls)
    {
        if ([aView isKindOfClass:[UISlider class]]){
            [(UISlider *)aView setEnabled:enabled];
        }
        if ([aView isKindOfClass:[UITextView class]]){
            [(UITextView *)aView setEditable:enabled];
        }
        // and so forth
    }
}
甜是你 2025-01-04 16:45:42

昨天我自己也遇到了这个问题。就我而言,设置 userInteractionEnabled 还不够,因为我希望控件显示为灰色,而不仅仅是停止响应触摸事件。我还有一些具有自定义启用/禁用行为的 UIView 子类,并且我不想按照 @NJones 的建议枚举所有类,以防将来添加更多控件。

正如 OP 所指出的,使用 NSNumber 不起作用。解决方案是使用 NSInspiration,如 TomSwift 对这个问题<的回答中所解释的那样< /a>.我决定将其包装在一个方便的函数中:

void XYPerformSelectorWithBool(id obj, SEL selector, BOOL boolean)
{
    NSMethodSignature *signature = [[obj class] instanceMethodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:selector];
    [invocation setArgument:&boolean atIndex:2];
    [invocation invokeWithTarget:obj];
}

然后禁用所有控件就像这样简单:

for (UIView *view in controls)
    if ([view respondsToSelector:@selector(setEnabled:)])
        XYPerformSelectorWithBool(view, @selector(setEnabled:), NO);

I came up against this problem myself yesterday. In my case, setting userInteractionEnabled wasn't sufficient, because I wanted the controls to appear greyed out, not just stop responding to touch events. I also had some UIView subclasses with custom enabled/disabled behavior, and I didn't want to have to enumerate all classes as @NJones suggested in case I add more controls in the future.

As the OP noted, using NSNumber does not work. The solution is to use NSInvocation as explained in TomSwift's answer to this question. I decided to wrap this in a convenience function:

void XYPerformSelectorWithBool(id obj, SEL selector, BOOL boolean)
{
    NSMethodSignature *signature = [[obj class] instanceMethodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:selector];
    [invocation setArgument:&boolean atIndex:2];
    [invocation invokeWithTarget:obj];
}

Then disabling all controls is as simple as:

for (UIView *view in controls)
    if ([view respondsToSelector:@selector(setEnabled:)])
        XYPerformSelectorWithBool(view, @selector(setEnabled:), NO);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文