美文网首页iOS开发攻城狮的集散地
利用runtime关联对象之给UIButton添加Block

利用runtime关联对象之给UIButton添加Block

作者: 一生谦卦 | 来源:发表于2018-01-30 13:13 被阅读14次

当我们想要给一个系统类添加一个属性的时候,假如不用继承的方式去实现,我们应该怎么办呢。有朋友想到了分类(category),但是category是不能为系统类添加新的成员变量的,我们可以再category中@property出来一个属性,但是他并不能生成带下划线的成员变量,也不能自动生成该变量的Setter和getter方法。实际上我们可以用runtime去实现为一个类的category添加新的属性并生成setter和getter方法。

本文通过一个实例去讲述如何给category添加一个属性

实例要求:给UIButton自定义一个方法初始化方法,通过Block去实现button绑定的事件。

关联对象:runtime给我们提供了如下的方法

//关联对象
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//获取关联的对象
id objc_getAssociatedObject(id object, const void *key)
//移除关联的对象
void objc_removeAssociatedObjects(id object)

参数说明:

id object:被关联的对象(如xiaoming)

const void *key:关联的key,要求唯一

id value:关联的对象(如dog)

objc_AssociationPolicy policy:内存管理的策略

内存管理策略:

OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */



OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.

                                        *   The association is not made atomically. */



OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied.

                                        *   The association is not made atomically. */



OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.

                                        *   The association is made atomically. */



OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.

                                        *   The association is made atomically. */

当对象给释放时会根据你所选择的策略来决定是否释放关联的对象,值得注意的是,我们不需要主动调用removeAssociated来接触关联的对象,如果需要解除指定的对象,可以使用setAssociatedObject置nil来实现。
UIButton+Block.h

//// UIButton+Block.h// ButtonBlock//// Created by 朱佳男 on 2018/1/5.// Copyright © 2018年 ShangYuKeJi. All rights reserved.//
#import <UIKit/UIKit.h>
typedef void (^ButtonActionBlock)(UIButton *button);
@interface UIButton (Block)
+(UIButton *)creatButtonWithFrame:(CGRect)frame title:(NSString *)title actionBlock:(ButtonActionBlock)actionBlock;

@end

UIButton+Block.m

//// UIButton+Block.m// ButtonBlock//// Created by 朱佳男 on 2018/1/5.// Copyright © 2018年 ShangYuKeJi. All rights reserved.//
#import "UIButton+Block.h"
#import <objc/message.h>
static const char *key = "actionKey";

@implementation UIButton (Block)

+(UIButton *)creatButtonWithFrame:(CGRect)frame title:(NSString *)title actionBlock:(ButtonActionBlock)actionBlock{
UIButton *button = [[UIButton alloc]init];
button.frame = frame;
[button setTitle:title forState:UIControlStateNormal];
[button addTarget:button action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
objc_setAssociatedObject(button, key, actionBlock, OBJC_ASSOCIATION_COPY);

return button;

}

-(void)buttonClick:(UIButton *)button{

ButtonActionBlock actionBlock1 = objc_getAssociatedObject(button, key);

if (actionBlock1) {

actionBlock1(button);

}
}

@end

使用方法

UIButton *button = [UIButton creatButtonWithFrame:CGRectMake(100, 100, 100, 44) title:@"我是按钮" actionBlock:^(UIButton *button) {

NSLog(@"我被点击了");

}];
button.backgroundColor = [UIColor orangeColor];
[self.view addSubview:button];

另一种写法

UIButton+Block.h

//// UIButton+Block.h// ButtonBlock//// Created by 朱佳男 on 2018/1/5.// Copyright © 2018年 ShangYuKeJi. All rights reserved.//

#import<UIKit/UIKit.h>
typedef void (^ButtonActionBlock)(UIButton *button);

@interface UIButton (Block)

@property (nonatomic ,copy)ButtonActionBlock actionBlock;

+(UIButton *)creatButtonWithFrame:(CGRect)frame title:(NSString *)title actionBlock:(ButtonActionBlock)actionBlock;

@end

UIButton+Block.m

//// UIButton+Block.m// ButtonBlock//// Created by 朱佳男 on 2018/1/5.// Copyright © 2018年 ShangYuKeJi. All rights reserved.//
#import "UIButton+Block.h"
#import<objc/message.h>
static const char *key2 = "propertyKey";

@implementation UIButton (Block)

+(UIButton *)creatButtonWithFrame:(CGRect)frame title:(NSString *)title actionBlock:(ButtonActionBlock)actionBlock{

UIButton *button = [[UIButton alloc]init];

button.frame = frame;

[button setTitle:title forState:UIControlStateNormal];

[button addTarget:button action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];

return button;

}

-(void)buttonClick:(UIButton *)button{

ButtonActionBlock actionBlock2 = self.actionBlock;

if (actionBlock2) {

actionBlock2(button);

}
}

-(void)setActionBlock:(ButtonActionBlock)actionBlock{

objc_setAssociatedObject(self, key2, actionBlock, OBJC_ASSOCIATION_COPY);

}

-(ButtonActionBlock)actionBlock{

return objc_getAssociatedObject(self, key2);

}

@end

使用方法

UIButton *button2 = [UIButton creatButtonWithFrame:CGRectMake(100, 200, 100, 44) title:@"我也是按钮" actionBlock:nil];

button2.actionBlock = ^(UIButton *button) {

NSLog(@"我也被点击了");

};

button2.backgroundColor = [UIColor orangeColor];

[self.view addSubview:button2];

相关文章

网友评论

    本文标题:利用runtime关联对象之给UIButton添加Block

    本文链接:https://www.haomeiwen.com/subject/gwtczxtx.html