カスタムビューボタンクリックイベント処理のいくつかの方法

6149 ワード

一、関連オブジェクト(runtime)


実際にはblockによって実現するもので、クラス目でUIButtonを作成するクリック拡張方法と見なすことができる.この方法の利点は、カスタムビューにbuttonを直接作成してビューに加えることであり、呼び出す必要がある場所でこの方法を呼び出すことで、buttonクリックイベントを実現することができ、カスタムビューごとに関連方法を書く必要がなく、コード量を減らすことができる.あまりよくないのは、オープンbuttonプロパティを作成する必要があり、変更される可能性があります.

関連オブジェクト


ネットワークからの抜粋:
関連オブジェクトをキーで区別することで、関連オブジェクトをNSDictionaryと考えることができ、関連オブジェクトの値を辞書のオブジェクトとして理解することができ、関連オブジェクトへのアクセスの値は辞書のsetObject:forKey:メソッドとobjectForKey:メソッドの両者に類似する違いは、関連オブジェクトのキーは不透明なポインタであり、不透明なポインタとは、その指すデータ構造が特定のタイプのポインタに限らないことである.関連オブジェクトを設定するときに、2つのキーを同じ値に一致させるには、両方が完全に同じポインタである必要があります.したがって、静的グローバル変数をキーとして使用すればいいです.
処理方法:
与えられたキーで関連付けられたオブジェクトの値を設定するobjc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)キー取得値objc_getAssociatedObject(id object, void *key)に従って関連付けられたオブジェクト`objc_をすべて除去するremoveAssociatedObject(id object)

buttonクラスパッケージング


まず、XXXXでクラスUIButton+XXXを作成します.h中:
#import 

typedef void(^ClickActionBlock)(UIButton *button);

@interface UIButton (ZYNBlock)

- (void)setClickBlock:(ClickActionBlock)block andEvent:(UIControlEvents)event;

@end

XXXでM中
#import "UIButton+ZYNBlock.h"
// 
#import 

static void *buttonClickKey = "buttonClickKey";

@implementation UIButton (ZYNBlock)

- (void)setClickBlock:(ClickActionBlock)block andEvent:(UIControlEvents)event {
    
    //  
    objc_setAssociatedObject(self, buttonClickKey, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
    
    [self addTarget:self action:@selector(buttonClick:) forControlEvents:event];
}

- (void)buttonClick:(UIButton *)button {
    
    //  
    ClickActionBlock block = objc_getAssociatedObject(self, buttonClickKey);
    
    if (block) {
        block(button);
    }
}

@end


使用方法


カスタムビューhファイルに関連button属性を開放する:
#import 

@interface JPSUserHeaderView : UIView

@property (nonatomic, weak) UIButton *closeArrow;

@end

カスタムビューm中
/** close button */
//  button ,  
    UIButton *closeArrow = [UIButton buttonWithType:UIButtonTypeCustom];
    [closeArrow setImage:[UIImage imageNamed:@"user_close"] forState:UIControlStateNormal];
    closeArrow.contentMode = UIViewContentModeScaleAspectFit;
    [self addSubview:closeArrow];
    
    self.closeArrow = closeArrow;

カスタムビューを追加するコントローラで、次の操作を行います.
- (void)setupSubViews {
    
    JPSUserHeaderView *headerView = [[JPSUserHeaderView alloc] initWithFrame:HeaderViewF];
    
    //   button  
    [headerView.closeArrow setClickBlock:^(UIButton *button) {
    //  
        [self dismissViewControllerAnimated:YES completion:nil];
    } andEvent:UIControlEventTouchUpInside];
    
    self.tableView.tableHeaderView = headerView;
    self.tableView.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0);
    self.tableView.showsVerticalScrollIndicator = NO;
    self.tableView.showsHorizontalScrollIndicator = NO;
    self.tableView.alwaysBounceVertical = NO;
    self.tableView.backgroundColor = [UIColor colorWithRed:0.908 green:0.926 blue:0.932 alpha:1.000];
    
    [self.tableView registerClass:[JPSTableViewCell class] forCellReuseIdentifier:cellIdentifier];
}


二、カスタムビューでblockを個別にバインドする


この方法は現在のカスタムビューにのみ適用されます.プロジェクトでこのカスタムビューがすべて使用されている場合は、関連するプロパティを外部に開く必要がなく、直接書くことができます.より安全です.

書き方


カスタムビューh中:
#import 

// typedef block block,  ,  = =
typedef void(^AvatarButtonBlock)(UIButton *button);

@interface JPSLearnHomeHeaderView : UIView

//  ,  
//@property (nonatomic, copy) AvatarButtonBlock block;

//  
- (void)setAvatarClick:(AvatarButtonBlock)block;

@end

カスタムビューm中
/** avatar */
    UIButton *avatar = [UIButton buttonWithType:UIButtonTypeCustom];
    [avatar setBackgroundImage:[UIImage imageNamed:@"user_avatar"] forState:UIControlStateNormal];
    avatar.layer.masksToBounds = YES;
    avatar.layer.cornerRadius = 12;
    
    //  ,  target/action block
    [avatar addTarget:self action:@selector(modalToUserPage:) forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:avatar];
//  
- (void)modalToUserPage:(UIButton *)button {
    if (self.clickEvent) {
        self.clickEvent(button);
    }
}

// block 
- (void)setAvatarClick:(AvatarButtonBlock)block {
    if (_clickEvent != block) {
        self.clickEvent = block;
    }
}

使用


カスタムビューを追加するコントローラ:
/** header view */
    JPSLearnHomeHeaderView *headerView = [[JPSLearnHomeHeaderView alloc] initWithFrame:HeaderViewF];
    
    //  :
    //   block  
    [headerView setAvatarClick:^(UIButton *button) {
        
        JPSUserTableController *userController = [[JPSUserTableController alloc] init];
        
        JPSNavController *nav = [[JPSNavController alloc] initWithRootViewController:userController];
        
        [self presentViewController:nav animated:YES completion:nil];
    }];
   
#if 0
    //  view block ,  
    headerView.block = ^(UIButton *button) {
       //     
       JPSUserTableController *userController = [[JPSUserTableController alloc] init];
        
       JPSNavController *nav = [[JPSNavController alloc] initWithRootViewController:userController];
        
       [self presentViewController:nav animated:YES completion:nil];
    };
#endif
    
    [self.view addSubview:headerView];

その他の実装方法

  • tableview data sourceエージェントメソッド中:(推奨せず、このように書くのは醜い)
  • - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        
        [cell.button addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
        
        return cell;
    }
    
  • エージェントの手順が多すぎて、簡単なイベントだけを処理する必要はないと感じています...しかし、エージェントは業務ロジックが複雑な場合に使いやすい.