1.為什么要寫這樣一個分類?
在應(yīng)用開發(fā)過程中贵白,我們經(jīng)常需要設(shè)置Label之間的行間距率拒,以及字間距,每次都是復(fù)制粘貼代碼禁荒,為了擺脫這種累贅猬膨,怎么才能在需要的時候只需要調(diào)用一次代碼就可以實現(xiàn)呢?因此就有了下面的代碼:
2.實現(xiàn)原理
為UILabel寫了一個分類呛伴,UILabel+SNExtension,在頭文件中勃痴,就添加兩個屬性。
/**
* 設(shè)置行間距
*/
@property (nonatomic, assign) CGFloat sn_lineSpace;
/**
* 設(shè)置字體之間的間距
*/
@property (nonatomic, assign) CGFloat sn_wordSpace;
在私有方法中热康,
#pragma mark - 利用Runtime為分類添加屬性
- (CGFloat)sn_lineSpace
{
return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setSn_lineSpace:(CGFloat)sn_lineSpace
{
objc_setAssociatedObject(self, @selector(sn_lineSpace), @(sn_lineSpace), OBJC_ASSOCIATION_RETAIN);
}
- (CGFloat)sn_wordSpace
{
return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setSn_wordSpace:(CGFloat)sn_wordSpace
{
objc_setAssociatedObject(self, @selector(sn_wordSpace), @(sn_wordSpace), OBJC_ASSOCIATION_RETAIN);
}
在load方法中我們通過 Swizze UIlabel的setText方法:
@implementation UILabel (SNExtension)
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL selectors[] = {
@selector(setText:),
};
for (NSUInteger index = 0; index < sizeof(selectors) / sizeof(SEL); ++index) {
SEL originalSelector = selectors[index];
SEL swizzledSelector = NSSelectorFromString([@"sn_" stringByAppendingString:NSStringFromSelector(originalSelector)]);
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
BOOL addedSuccess = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (addedSuccess)
{
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else
{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
});
}
- (void)sn_setText:(NSString *)text
{
[self sn_setText:text];
if (self.sn_lineSpace > 0)
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = self.sn_lineSpace;
paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;
paragraphStyle.lineBreakMode = self.lineBreakMode;
paragraphStyle.alignment = self.textAlignment;
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.text length])];
[attributedString addAttribute:NSFontAttributeName value:self.font range:NSMakeRange(0, [self.text length])];
self.attributedText = attributedString;
}
if (self.sn_wordSpace > 0 )
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
[attributedString addAttribute:(__bridge NSString *)kCTKernAttributeName value:@(self.sn_wordSpace) range:NSMakeRange(0, [attributedString length])];
self.attributedText = attributedString;
}
}
貌似通過上面的代碼就可以解決問題召耘,我們在使用的時候,就可以
self.contentLabel.sn_lineSpace = 6.f;
但是這樣會有一個問題褐隆,就是如果我們是先給Label復(fù)制然后在設(shè)置行間距是沒有問題的,但是如果我們先給Label復(fù)制剖踊,然后在設(shè)置行間距庶弃,這個時候這個方法就不會生效。如何解決這個問題呢德澈,我們需要做這樣一個操作歇攻。我們需要同時swizze layoutSubviews方法,這樣就可以了。
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL selectors[] = {
@selector(setText:),
@selector(layoutSubviews)
};
});
}
- (void)sn_layoutSubviews
{
[self sn_layoutSubviews];
if (self.sn_lineSpace > 0)
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = self.sn_lineSpace;
paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;
// paragraphStyle.paragraphSpacing = 0.f;
paragraphStyle.lineBreakMode = self.lineBreakMode;
paragraphStyle.alignment = self.textAlignment;
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [self.text length])];
[attributedString addAttribute:NSFontAttributeName value:self.font range:NSMakeRange(0, [self.text length])];
self.attributedText = attributedString;
}
if (self.sn_wordSpace > 0 )
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
[attributedString addAttribute:(__bridge NSString *)kCTKernAttributeName value:@(self.sn_wordSpace) range:NSMakeRange(0, [attributedString length])];
self.attributedText = attributedString;
}
}