示例: 一鍵改字體
1. 工程的Info.plist文件中需添加:
Info.plist添加內(nèi)容.png
其中l(wèi)oveway.ttf為字體冊(cè)資源文件的名稱.
2. Category類
UILabel+FontChange.h
//
// UILabel+FontChange.h
// FontChangeProject
//
// Created by Brian on 16/02/13.
// Copyright ? 2016年 Mac. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UILabel (FontChange)
@end
UILabel+FontChange.m
//
// UILabel+FontChange.m
// FontChangeProject
//
// Created by Brian on 16/02/13.
// Copyright ? 2016年 Mac. All rights reserved.
//
#import "UILabel+FontChange.h"
#import <objc/runtime.h>
#define CustomFontName @"FZLBJW--GB1-0" // 字體冊(cè).ttf文件中字體的名稱
@implementation UILabel (FontChange)
+ (void)load {
// 方法交換應(yīng)該保證在程序中只會(huì)被執(zhí)行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 1. 獲取UILabel的生命周期方法的selector
SEL originalSel = @selector(willMoveToSuperview:);
// 2. 獲取自己實(shí)現(xiàn)的將要被交換的方法的selector
SEL overrideSel = @selector(myWillMoveToSuperview:);
// 3. 實(shí)現(xiàn)方法交換
MethodSwizzle([self class], originalSel, overrideSel);
});
}
void MethodSwizzle(Class cls, SEL originalName, SEL overrideName) {
// 獲取類中的某個(gè)實(shí)例的方法(減號(hào)方法)
Method originalMethod = class_getInstanceMethod(cls, originalName);
Method overrideMethod = class_getInstanceMethod(cls, overrideName);
/** 原理: 有兩種情況要考慮一下,
第一種情況是:要復(fù)寫的方法(override)并沒有在目標(biāo)類中實(shí)現(xiàn);
第二種情況是:這個(gè)方法(override)已經(jīng)存在于目標(biāo)類中了.
這兩種情況要區(qū)別對(duì)待.
對(duì)于第一種情況,應(yīng)當(dāng)先在目標(biāo)類中增加一個(gè)新的實(shí)現(xiàn)方法(override),運(yùn)行時(shí)函數(shù)class_addMethod()如果
發(fā)現(xiàn)該方法已經(jīng)存在,會(huì)返回NO;
對(duì)于第二種情況,因?yàn)閏lass_getInstanceMethod會(huì)返回父類的實(shí)現(xiàn),如果直接替換,就會(huì)替換掉父類的實(shí)現(xiàn),而不是目標(biāo)類中的實(shí)現(xiàn).
這時(shí)需要在一個(gè)合適的位置來調(diào)用MethodSwizzle()方法, 在+ (void)load方法中調(diào)用就可以直接完成交換.
*/
// class_addMethod()方法會(huì)讓originalName方法指向新的實(shí)現(xiàn)overrideMethod
BOOL result = class_addMethod(cls, originalName, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod));
if (result) {
// 如果添加成功, 表示originalName方法已指向新的實(shí)現(xiàn)overrideMethod, 然后再使用class_replaceMethod()將新的方法overrideName指向原先的實(shí)現(xiàn)originalMethod, 就完成了交換.
class_replaceMethod(cls, overrideName, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
// 如果添加失敗,就是第二種情況,這時(shí)可以直接通過method_exchangeImplementations來完成交換.
method_exchangeImplementations(originalMethod, overrideMethod);
}
}
- (void)myWillMoveToSuperview:(UIView *)newSuperview {
[self myWillMoveToSuperview:newSuperview];
// 自己的處理代碼...
if ([self isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
return;
}
if (self) {
if (self.tag == 10086) {
self.font = [UIFont systemFontOfSize:self.font.pointSize];
} else {
if ([UIFont fontNamesForFamilyName:CustomFontName]) {
self.font = [UIFont fontWithName:CustomFontName size:self.font.pointSize];
}
}
}
}
@end
Tips: 獲取字體冊(cè)中的字體名稱
/**
讀取ttf或otf字體冊(cè)中的字體名稱 (先在Info.plist中把字體文件名添加到Fonts provided by application一項(xiàng)中)
@param path 字體冊(cè)文件的路徑 如:[[NSBundle mainBundle] pathForResource:@"font12" ofType:@"ttf"]
@param size 字體大小 如:18
@return 字體
*/
- (UIFont *)customFontWithPath:(NSString *)path size:(CGFloat)size {
NSURL *fontUrl = [NSURL fileURLWithPath:path];
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL((__bridge CFURLRef)fontUrl);
CGFontRef fontRef = CGFontCreateWithDataProvider(fontDataProvider);
CGDataProviderRelease(fontDataProvider);
CTFontManagerRegisterGraphicsFont(fontRef, NULL);
NSString *fontName = CFBridgingRelease(CGFontCopyPostScriptName(fontRef));
NSLog(@"fontName = %@", fontName);
UIFont *font = [UIFont fontWithName:fontName size:size];
CGFontRelease(fontRef);
return font;
}
/**
讀取ttc字體冊(cè)中的字體名稱 (先在Info.plist中把字體文件名添加到Fonts provided by application一項(xiàng)中)
@param path 字體冊(cè)文件的路徑 如:[[NSBundle mainBundle] pathForResource:@"font12" ofType:@"ttc"]
@param size 字體大小 如:18
@return 字體數(shù)組
*/
- (NSArray *)customFontArrayWithPath:(NSString *)path size:(CGFloat)size {
CFStringRef fontPath = CFStringCreateWithCString(NULL, [path UTF8String], kCFStringEncodingUTF8);
CFURLRef fontUrl = CFURLCreateWithFileSystemPath(NULL, fontPath, kCFURLPOSIXPathStyle, 0);
CFArrayRef fontArray = CTFontManagerCreateFontDescriptorsFromURL(fontUrl);
CTFontManagerRegisterFontsForURL(fontUrl, kCTFontManagerScopeNone, NULL);
NSMutableArray *customFontArray = [NSMutableArray array];
for (CFIndex i = 0; i < CFArrayGetCount(fontArray); i++) {
CTFontDescriptorRef descriptor = CFArrayGetValueAtIndex(fontArray, i);
CTFontRef fontRef = CTFontCreateWithFontDescriptor(descriptor, size, NULL);
NSString *fontName = CFBridgingRelease(CTFontCopyName(fontRef, kCTFontPostScriptNameKey));
NSLog(@"fontName[%ld] = %@", i, fontName);
UIFont *font = [UIFont fontWithName:fontName size:size];
[customFontArray addObject:font];
}
return customFontArray;
}