Отключить все подпредставления в коллекции IBOutletCollection - PullRequest
1 голос
/ 24 января 2012

Я хочу отключить / включить все UIViews в IBOutletCollection.Однако UIViews различаются по классу, поэтому я не могу вызвать setEnabled напрямую.

Тогда я подумал, что для этого буду использовать метод performSelector, однако я могу только отправить Object в качестве параметра.

Я читал как на этом сайте, так и на других сайтах, что я мог бы просто использовать [NSNumber numberWithBool YES/NO], однако включенное состояние не изменяется при отправке NSNumber с bool YES или NO.

Я получил отключенную часть для работы с помощью 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;
    }
}

Где элементы управления - это IBOutletCollection, состоящая из UISliders, UIButtons, UITextViews и UITextfields,(@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *controls;)

Примечание: UITextViews отлично работает с приведенным выше кодом, это только другой тип UIViews, который использует setEnabled.

Ответы [ 2 ]

1 голос
/ 24 января 2012

Есть ли конкретная причина, по которой вы не используете 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
    }
}
0 голосов
/ 29 декабря 2015

Я сам вчера столкнулся с этой проблемой.В моем случае настройки userInteractionEnabled было недостаточно, потому что я хотел, чтобы элементы управления выглядели серыми, а не просто перестали реагировать на сенсорные события.У меня также было несколько подклассов UIView с пользовательским включенным / отключенным поведением, и я не хотел перечислять все классы, как предложил @NJones, на случай, если в будущем я добавлю больше элементов управления.

Как отметил OP,использование NSNumber не работает.Решение состоит в том, чтобы использовать NSInvocation, как объяснено в ответе TomSwift на на этот вопрос .Я решил обернуть это в удобную функцию:

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);
...