Задачи UIButton не работают, если UIView добавлен как подвью

У меня есть UIButton. Он имеет два подхода. Затем я вызываю:

[createButton addTarget:self action:@selector(openComposer) forControlEvents:UIControlEventTouchUpInside];

Если я коснусь частей UIButton, которые не охвачены, кроме одного из его подзонов, он работает нормально. Однако, если я коснусь одного из подзонов, это не вызывает действие.

В обоих подзонах я имеет .userInteractionEnabled значение YES.

Оба подзона равны UIViews с frame и backgroundColor.

Как я могу получить крану "пройти" через UIView и на UIButton?

Спасибо

EDIT: Мне нужно использовать UIControlEvents, потому что мне нужен UIControlEventTouchDown.

ИЗМЕНИТЬ 2:

Вот код кнопки.

@interface CreateButton ()

@property (nonatomic) Theme *theme;
@property (nonatomic) UIView *verticle;
@property (nonatomic) UIView *horizontal;
@property (nonatomic) BOOL mini;

@end

@implementation CreateButton

#pragma mark - Accessors

- (UIView *)verticle {
    if (! _verticle) {
        _verticle = [[UIView alloc] init];
        _verticle.backgroundColor = [self.theme colorForKey:@"createButtonPlusBackgroundColor"];
        _verticle.userInteractionEnabled = NO;
    }
    return _verticle;
}

- (UIView *)horizontal {
    if (! _horizontal) {
        _horizontal = [[UIView alloc] init];
        _horizontal.backgroundColor = [self.theme colorForKey:@"createButtonPlusBackgroundColor"];
        _verticle.userInteractionEnabled = NO;
    }
    return _horizontal;
}

#pragma mark - Init

- (instancetype)initWithTheme:(Theme *)theme frame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _theme = theme;

        self.layer.cornerRadius = roundf(frame.size.width / 2);
        self.layer.shadowColor = [UIColor blackColor].CGColor;
        self.layer.shadowOpacity = .1f;
        self.layer.shadowOffset = CGSizeZero;
        self.layer.shadowRadius = 15.f;
        self.backgroundColor = [self.theme colorForKey:@"createButtonBackgroundColor"];

        [self addSubview:self.verticle];
        [self addSubview:self.horizontal];

        [self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchDown];
        [self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchUpInside];
        [self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchUpOutside];
    }
    return self;
}

#pragma mark - Actions

- (void)animate {
    [UIView animateWithDuration:0.2 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:8 options:kNilOptions animations:^{
        if (self.mini) {
            self.transform = CGAffineTransformMakeScale(1.0, 1.0);
            self.mini = NO;
        } else {
            self.transform = CGAffineTransformMakeScale(0.90, 0.90);
            self.mini = YES;
        }
    } completion:nil];
}

#pragma mark - UIView

- (void)layoutSubviews {
    CGSize size = self.bounds.size;

    NSInteger width = 3;
    NSInteger verticleInset = 12;
    self.verticle.frame = CGRectMake((size.width - width) / 2, verticleInset, width, size.height - (verticleInset * 2));
    self.horizontal.frame = CGRectMake(verticleInset, (size.height - width) / 2, size.width - (verticleInset * 2), width);
}

@end

Ответ 1

Установите userInteractionEnabled в NO, чтобы ваши подпункты позволяли касаниям проходить через них и на вашу кнопку.

Также не забудьте изменить _verticle.userInteractionEnabled = NO; в своем ленивом загрузчике для вашего свойства horizontal на _horizontal.userInteractionEnabled = NO;, поскольку я считаю, что опечатка.

Ответ 2

используйте код, как показано ниже (замените "ViewControllerFilterCategory" своим собственным + nibName), чтобы добавить контроллер из nib (дочерний один) в качестве дочернего контроллера текущего контроллера, прежде чем добавлять представление в виде суб-представления. Затем iOS будет вызывать действия, прикрепленные к дочернему контроллеру, как вы ожидаете:

    let vcCats = ViewControllerFilterCategory(nibName: "ViewControllerFilterCategory", bundle: Bundle.main);
    self.addChildViewController(vcCats);
    self.view.addSubview(vcCats.view);

P.S. не забудьте вызвать 'removeFromParentViewController' перед удалением вашего подвидного представления (например, ниже):

@IBAction func onCanceled(_ sender: Any) {
    self.removeFromParentViewController()
    self.view.removeFromSuperview()
}

Ответ 3

Я столкнулся с этой проблемой.

В моем случае у меня был nib, загруженный как subview.

UIViewController *vc = [[[NSClassFromString(@"nib_controller") alloc] initWithNibName:@"nib_name" bundle:nil] autorelease];
[self.view addSubview:vc.view];

В представлении nib (vc.view) все кнопки не вызывали действие.

[(UIButton*)[self.view viewWithTag:button_tag] addTarget:self action:@selector(btnActions:) forControlEvents:UIControlEventTouchUpInside];


-(IBAction)btnActions:(id)sender{

    // list star buttons for bookmark
    NSLog(@"btnActions tag %d", [sender tag]);

    // bla bla bla
}

Мне удалось коснуться кнопок, но метод btnActions не был запущен.

Тогда я просто попробовал что-то очень простое и логичное.

На родительском контроллере представления у меня есть метод с тем же именем:

-(IBAction)btnActions:(id)sender{

    // list star buttons for bookmark
    NSLog(@"parent btnActions tag %d", [sender tag]);

    // bla bla bla
}

Я просто добавил NSLog внутри, чтобы узнать, что произойдет. Результат появился на консоли журнала:

parent btnActions tag xxx

Это было невозможно в версиях iOS, предшествующих 9.

Но теперь его можно получить доступ к методам из родительского представления, если представление загружено из представления контроллера nib.

Для тех, кто все еще запутывается, см. ниже рисунок

родительский → A
ребенок > B

----------
|        | 
|   A    |
|        |
----------
    |
    |--- -(IBAction)btnActions:(id)sender


----------
|        | 
|   B    |
|        |
----------
    |
    |--- -(IBAction)btnActions:(id)sender (the controller have an method with same name as parent)

B.View добавляется из контроллера A

----------
|        | 
|   A    |
|        |
----------
    |
    |--- (touching some button -> execute this:

UIViewController *B = [[[NSClassFromString(@"B_controller") alloc] initWithNibName:@"B_name" bundle:nil] autorelease];
[self.view addSubview:B.view]; // The B.view is added as subview.

Кнопки внутри B.view отправляют действия на -(IBAction)btnActions

Пример

[(UIButton*)[self.view viewWithTag:button_tag] addTarget:self action:@selector(btnActions:) forControlEvents:UIControlEventTouchUpInside];

Все кнопки работают хорошо, потому что все их можно было коснуться или щелкнуть (симулятор xcode). Но метод -(IBAction)btnActions, объявленный в B.controller, не вызывался. Я пытался решить это в течение многих часов, пока не понял, что действия отправляются в A.Controller, как описано выше.

Головная боль здесь в ранних версиях iOS была невозможна.

Я не уверен, но я думаю, что из iOS9 у нас есть это другое поведение.

Приложение работает хорошо до iOS8.