iOS利用runtime关联对象给分类添加属性

日常开发过程中我们经常碰到要给分类添加自定义属性和变量的,下面通过关联对象给分类添加属性,也是runtime的实际应用之一,非常实用。(关于runtime的使用还有很多,这里只简单记录一下利用runtime给分类添加属性)。

关联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;被关联的对象

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

id value:关联的对象

objc_AssociationPolicy policy:内存管理策略

1.给UILabel添加一个 竖直方向的verticalText,如下图所示:

竖直方向的label.png

新建一个继承UILabel的Category,并添加一个成员变量
.h文件

#import 

NS_ASSUME_NONNULL_BEGIN

@interface UILabel (HXVertical)

@property (nonatomic) NSString * verticalText;

@end

NS_ASSUME_NONNULL_END

m.文件

#import "UILabel+HXVertical.h"
#import "objc/Runtime.h"
@implementation UILabel (HXVertical)


- (NSString *)verticalText{
    // 获取关联对象
    return objc_getAssociatedObject(self, @selector(verticalText));
}

- (void)setVerticalText:(NSString *)verticalText{

    //关联对象
    objc_setAssociatedObject(self, &verticalText, verticalText, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    NSMutableString *str = [[NSMutableString alloc] initWithString:verticalText];
    NSInteger count = str.length;
    for (int i = 1; i < count; i ++) {
        [str insertString:@"\n" atIndex:i*2-1];
    }
    self.text = str;
    self.numberOfLines = 0;
}

@end

调用时就直接使用点语法:
_textLabel.verticalText = @"厉害了,我的国";

2.给UIButton添加一个扩大点击区域的实例方法
新建一个继承UIButton的Category,并添加一个实例方法
.h文件

#import 

@interface UIButton (HXEnlargeTouchArea)

- (void)setTouchExpandEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left;
@end

.m文件

#import "UIButton+HXEnlargeTouchArea.h"
#import 
@implementation UIButton (HXEnlargeTouchArea)

static char topRegion;
static char rightRegion;
static char bottomRegion;
static char leftRegion;

- (void)setTouchExpandEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left {

    //关联对象
    objc_setAssociatedObject(self, &topRegion, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &rightRegion, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &bottomRegion, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &leftRegion, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (CGRect)expandRect
{
    
    //获取关联对象
    NSNumber* topEdge = objc_getAssociatedObject(self, &topRegion);
    NSNumber* rightEdge = objc_getAssociatedObject(self, &rightRegion);
    NSNumber* bottomEdge = objc_getAssociatedObject(self, &bottomRegion);
    NSNumber* leftEdge = objc_getAssociatedObject(self, &leftRegion);
    if (topEdge && rightEdge && bottomEdge && leftEdge)
    {
        return CGRectMake(self.bounds.origin.x - leftEdge.floatValue,self.bounds.origin.y - topEdge.floatValue,self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue,self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);
    }
    else
    {
        return self.bounds;
    }
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
    CGRect rect = [self expandRect];
    if (CGRectEqualToRect(rect, self.bounds))
    {
        return [super hitTest:point withEvent:event];
    }
    return CGRectContainsPoint(rect, point) ? self : nil;
}
@end

创建button并调用:
[button setTouchExpandEdgeWithTop:30 right:30 bottom:30 left:30];
点击button的上下左右各30pt,button也会有响应。

Demo链接

你可能感兴趣的:(iOS利用runtime关联对象给分类添加属性)