示例: 一鍵改字體
1. 工程的Info.plist文件中需添加:
Info.plist添加內(nèi)容.png
其中l(wèi)oveway.ttf為字體冊資源文件的名稱.
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" // 字體冊.ttf文件中字體的名稱
@implementation UILabel (FontChange)
+ (void)load {
// 方法交換應(yīng)該保證在程序中只會被執(zhí)行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 1. 獲取UILabel的生命周期方法的selector
SEL originalSel = @selector(willMoveToSuperview:);
// 2. 獲取自己實現(xiàn)的將要被交換的方法的selector
SEL overrideSel = @selector(myWillMoveToSuperview:);
// 3. 實現(xiàn)方法交換
MethodSwizzle([self class], originalSel, overrideSel);
});
}
void MethodSwizzle(Class cls, SEL originalName, SEL overrideName) {
// 獲取類中的某個實例的方法(減號方法)
Method originalMethod = class_getInstanceMethod(cls, originalName);
Method overrideMethod = class_getInstanceMethod(cls, overrideName);
/** 原理: 有兩種情況要考慮一下,
第一種情況是:要復(fù)寫的方法(override)并沒有在目標類中實現(xiàn);
第二種情況是:這個方法(override)已經(jīng)存在于目標類中了.
這兩種情況要區(qū)別對待.
對于第一種情況,應(yīng)當(dāng)先在目標類中增加一個新的實現(xiàn)方法(override),運行時函數(shù)class_addMethod()如果
發(fā)現(xiàn)該方法已經(jīng)存在,會返回NO;
對于第二種情況,因為class_getInstanceMethod會返回父類的實現(xiàn),如果直接替換,就會替換掉父類的實現(xiàn),而不是目標類中的實現(xiàn).
這時需要在一個合適的位置來調(diào)用MethodSwizzle()方法, 在+ (void)load方法中調(diào)用就可以直接完成交換.
*/
// class_addMethod()方法會讓originalName方法指向新的實現(xiàn)overrideMethod
BOOL result = class_addMethod(cls, originalName, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod));
if (result) {
// 如果添加成功, 表示originalName方法已指向新的實現(xiàn)overrideMethod, 然后再使用class_replaceMethod()將新的方法overrideName指向原先的實現(xiàn)originalMethod, 就完成了交換.
class_replaceMethod(cls, overrideName, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
// 如果添加失敗,就是第二種情況,這時可以直接通過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: 獲取字體冊中的字體名稱
/**
讀取ttf或otf字體冊中的字體名稱 (先在Info.plist中把字體文件名添加到Fonts provided by application一項中)
@param path 字體冊文件的路徑 如:[[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字體冊中的字體名稱 (先在Info.plist中把字體文件名添加到Fonts provided by application一項中)
@param path 字體冊文件的路徑 如:[[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;
}