iOS UILabel 添加 edgeInsets 间距
用类别的方式,来实现label的内边距。
UILabel+myEdgeInsets.h
#import@interface UILabel (myEdgeInsets)
@property (nonatomic, assign)UIEdgeInsets edgeInsets;
@end
UILabel+myEdgeInsets.m
#import "UILabel+myEdgeInsets.h"
@implementation UILabel (myEdgeInsets)
// 钩子
+ (void)load {
method_exchangeImplementations(class_getInstanceMethod(self.class, @selector(textRectForBounds:limitedToNumberOfLines:)),
class_getInstanceMethod(self.class, @selector(sxt_textRectForBounds:sxt_limitedToNumberOfLines:)));
method_exchangeImplementations(class_getInstanceMethod(self.class, @selector(drawTextInRect:)),
class_getInstanceMethod(self.class, @selector(sxt_drawTextInRect:)));
}
//runTime 关联
- (void)setEdgeInsets:(UIEdgeInsets)edgeInsets{
//id 不让放struct 类型
NSArray * arr = @[@(edgeInsets.top),@(edgeInsets.left),@(edgeInsets.bottom),@(edgeInsets.right)];
objc_setAssociatedObject(self, @selector(edgeInsets), arr, OBJC_ASSOCIATION_RETAIN);
}
- (UIEdgeInsets)edgeInsets{
NSArray * arr = objc_getAssociatedObject(self, @selector(edgeInsets));
return UIEdgeInsetsMake([arr[0] floatValue], [arr[1] floatValue], [arr[2] floatValue], [arr[3] floatValue]);
}
#pragma mark -
// 修改绘制文字的区域,edgeInsets增加bounds
-(CGRect)sxt_textRectForBounds:(CGRect)bounds sxt_limitedToNumberOfLines:(NSInteger)numberOfLines{
/*
注意传入的UIEdgeInsetsInsetRect(bounds, self.edgeInsets),bounds是真正的绘图区域
CGRect rect = [super textRectForBounds: limitedToNumberOfLines:numberOfLines];
类别中不能使用 super 用黑魔法替换方法
*/
CGRect rect = [self sxt_textRectForBounds:UIEdgeInsetsInsetRect(bounds,self.edgeInsets) sxt_limitedToNumberOfLines:numberOfLines];
//根据edgeInsets,修改绘制文字的bounds
rect.origin.x -= self.edgeInsets.left;
rect.origin.y -= self.edgeInsets.top;
rect.size.width += self.edgeInsets.left + self.edgeInsets.right;
rect.size.height += self.edgeInsets.top + self.edgeInsets.bottom;
return rect;
}
//绘制文字
- (void)sxt_drawTextInRect:(CGRect)rect{
//令绘制区域为原始区域,增加的内边距区域不绘制
[self sxt_drawTextInRect:UIEdgeInsetsInsetRect(rect, self.edgeInsets)];
}
@end
过程中遇到了几个问题:
1.类别中不能添加成员属性
解决:用runtime 关联的方式 实现set get方法。
2.用runtime objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>) 中的id 放不了UIEdgeInsets(struct 类型)
解决:存关联的时候转化成数组 ,取的时候再转化回来。
3.类别中不能用 super(重写方法时候要用super)
解决:用method_exchangeImplementations(黑魔法 钩子)替换方法的调用。(就相当于把self调用这个方法当做了super,然后在自己替换的方法中写 添加边距)
希望能对你有所帮助,欢迎指点。:-D