分享工作中Runtime关联对象的使用

2019-01-08  本文已影响3人  小苗晓雪

分享在分类中两个 objc_setAssociatedObject / objc_getAssociatedObject 关联对象方法的一点使用
ViewController.m文件

#import "ViewController.h"
#import <objc/runtime.h>
#import "UIButton+ActionButtonBlock.h"

#define ScreenWidth self.view.frame.size.width

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self setupUI];
}


- (void)setupUI
{
    // 第一个按钮:
    UIButton *button1 = [UIButton createBtnWithFrame:CGRectMake((ScreenWidth - 100) / 2, (ScreenWidth - 50) / 2 - 50, 100, 50) title:@"按钮A" ActionButtonBlock:^(UIButton *button) {
        
        float r = random()%255/255.0;
        float g = random()%255/255.0;
        float b = random()%255/255.0;
        self.view.backgroundColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0f];
        
    }];
    button1.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:button1];
    
    // 第二个按钮:
    UIButton *button2 = [UIButton createBtnWithFrame:CGRectMake((ScreenWidth - 100) / 2, CGRectGetMaxY(button1.frame) + 50, 100, 50) title:@"按钮B" ActionButtonBlock:nil];
    button2.actionButtonBlock = ^(UIButton *button) {
        
        NSLog(@"button.titleLabel.text = %@",button.titleLabel.text);
        
    };
    button2.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:button2];
    
    // 第三个按钮:
    UIButton *button3 = [UIButton createBtnWithFrame:CGRectMake((ScreenWidth - 100) / 2, CGRectGetMaxY(button2.frame) + 50, 100, 50) title:@"按钮C" ActionButtonBlock:nil];
    button3.buttonBlock = ^(UIButton *button) {
        
        NSLog(@"点击了按钮3");
        
    };
    button3.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:button3];
}

@end

UIButton+ActionButtonBlock.h文件

#import <UIKit/UIKit.h>
#import <objc/runtime.h>

typedef void (^ActionButtonBlock)(UIButton *button);
typedef void (^ButtonBlock)(UIButton *button);

@interface UIButton (ActionButtonBlock)

@property(nonatomic, copy) ActionButtonBlock actionButtonBlock;
@property (nonatomic, copy) ButtonBlock buttonBlock;
+ (UIButton *)createBtnWithFrame:(CGRect)frame title:(NSString *)title ActionButtonBlock:(ActionButtonBlock)actionButtonBlock;

@end

UIButton+ActionButtonBlock.m文件

#import "UIButton+ActionButtonBlock.h"

static NSString *const kOfMethod;
static NSString *const kOfProperty;
static NSString *const kOfBlock;


@implementation UIButton (ActionButtonBlock)

+ (UIButton *)createBtnWithFrame:(CGRect)frame title:(NSString *)title ActionButtonBlock:(ActionButtonBlock)actionButtonBlock
{
    UIButton *button = [[UIButton alloc]init];
    button.frame = frame;
    [button setTitle:title forState:UIControlStateNormal];
    [button addTarget:button action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    
    // 1.这里两个block中的其中一个 , 它是你再初始化我这个button类的时候就带着的block , 他是通过方法key与button关联的block kOfMethod
    objc_setAssociatedObject(button, &kOfMethod, actionButtonBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
    
    return button;
}

- (void)buttonClicked:(UIButton *)button
{
    // 获取两个个block
    ActionButtonBlock block1 = objc_getAssociatedObject(button, &kOfMethod);
    ActionButtonBlock block2 = objc_getAssociatedObject(button, &kOfProperty);
    if (block1)
    {
        block1(button);
    }
    else if (block2)
    {
        block2(button);
    }
    else if (self.buttonBlock)
    {
        self.buttonBlock(button);
    }
}

#pragma mark - 按钮 B 的 actionButtonBlock属性 的 Seter / Getter 方法
// 2.这是属性block的方法关联 , 他是通过属性的set / get方法与button相关联的 , 所以一会儿在viewController里你创建block 的时候如果block写nil , 再新的一行里通过button2.actionButtonBlock = ^(UIButton *button) { ... }; 这种属性的方法追加block那就是通过这种方法关联的block , 而不是初始化的那种block追加;
// 让 actionButtonBlock 作为UIButton的一个属性 , 让这个属性的set / get 方法与button自身关联
// 这里的关联写的是self , 这个self就是button啊 , 可别想成别的什么~
- (void)setActionButtonBlock:(ActionButtonBlock)actionButtonBlock
{
    objc_setAssociatedObject(self, &kOfProperty, actionButtonBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (ActionButtonBlock)actionButtonBlock
{
    return objc_getAssociatedObject(self, &kOfProperty);
}


#pragma mark - 按钮 C 的 buttonBlock 属性 的 Seter / Getter 方法
// 必须要关联对象才行 , 分类不能直接写set / get方法的实现
- (void)setButtonBlock:(ButtonBlock)buttonBlock
{
    objc_setAssociatedObject(self, &kOfBlock, buttonBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (ButtonBlock)buttonBlock
{
    return objc_getAssociatedObject(self, &kOfBlock);
}

@end

参考文章 : https://blog.csdn.net/u014220518/article/details/52873164
感谢作者的分享!

愿编程让这个世界更美好

上一篇 下一篇

猜你喜欢

热点阅读