web-dev-qa-db-ja.com

UIViewがサブビューとして追加された場合、UIButtonターゲットが機能しない

UIButtonがあります。 2つのサブビューがあります。次に電話する:

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

覆われていないがそのサブビューの1つであるUIButtonの部分をタップすると、正常に機能します。ただし、代わりにサブビューの1つをタップしても、アクションはトリガーされません。

両方のサブビューに、.userInteractionEnabledYESに設定されます。

両方のサブビューは、UIViewsframeを持つプレーンbackgroundColorsです。

タップを取得してUIViewUIButtonに「パススルー」するにはどうすればよいですか?

ありがとう

EDIT: UIControlEventTouchDownが必要なため、UIControlEventsを使用する必要があります。

編集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
19
Jason Silberman

サブビューのuserInteractionEnabledNOに設定すると、タッチがそれらを通過してボタンに到達します。

また、horizontalプロパティのレイジーローダーで_verticle.userInteractionEnabled = NO;_horizontal.userInteractionEnabled = NO;に変更してください。これはタイプミスだと思います。

32

次のようなコードを使用して(「ViewControllerFilterCategory」を独自のもの+ nibNameに置き換えて)、サブビューとしてビューを追加する前に、現在のコントローラーの子コントローラーとしてnib(子1)からコントローラーを追加してください。次に、iOSは、期待どおりに子コントローラーにアタッチされたアクションを呼び出します。

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

追伸サブビューを削除する前に、「removeFromParentViewController」を呼び出すことを忘れないでください(以下を参照)。

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

私はこの問題に直面しました。

私の場合、ペン先をサブビューとしてロードしました。

_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は起動されていませんでした。

それから、私は本当にシンプルで論理的なものを試しました。

親View Controllerでは、同じ名前のメソッドがあります:

_-(IBAction)btnActions:(id)sender{

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

    // bla bla bla
}
_

NSLogを内部に追加して、何が起こるかを確認しました。結果はログコンソールに表示されました。

_parent btnActions tag xxx
_

これは、以前のバージョン9のiOSでは不可能でした。

しかし、今では、ビューがnibコントローラビューからロードされる場合、親ビューからメソッドにアクセスできます。

まだ混乱している人については、以下の図を参照してください

-> A
child> B

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


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

B.viewはコントローラーから追加されます

_----------
|        | 
|   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シミュレーター)、すべてのボタンが正常に機能しているようです。しかし、_B.controller_に宣言された-(IBAction)btnActionsメソッドは呼び出されていませんでした。上記のように、アクションが_A.Controller_に送信されていることに気付くまで、これを何時間も解決し続けました。

ここでの頭痛の種は、iOSの初期バージョンではこれが不可能だったことです。

よくわかりませんが、iOS9からは、この異なる動作があると思います。

このアプリはiOS8までうまく機能していました。

0
Daniel Omine