基本原理
1.计算iPhone屏幕尺寸与UI设计稿的尺寸比例
2.利用runtime机制,将原始字体大小值进行比例缩放,并替换原生方法的实现
代码适配替换方法(UIFont),可根据需求自行追加其他方法:
+ (UIFont *)systemFontOfSize:(CGFloat)fontSize;
+ (nullable UIFont *)fontWithName:(NSString *)fontName size:(CGFloat)fontSize;
xib适配替换方法(UILabel):
- (void)awakeFromNib;
代码适配
#import "UIFont+ScaleAdapter.h"
#import <objc/runtime.h>
//UI设计图宽度
#define DesignWidth 414.0
//缩放比例
#define Scaling ((CGFloat)([UIScreen mainScreen].bounds.size.width / DesignWidth))
@implementation UIFont (ScaleAdapter)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//要特别注意你替换的方法到底是哪个性质的方法(实例方法:Class class = [self class]; 类方法:Class class = object_getClass((id)self);)
//类方法的写法
Class class = object_getClass((id)self);
// 获取系统的selector
SEL originalSelector = @selector(systemFontOfSize:);
SEL originalSelector1 = @selector(fontWithName:size:);
// 自己要交换的selector
SEL swizzledSelector = @selector(tc_systemFontOfSize:);
SEL swizzledSelector1 = @selector(tc_fontWithName:size:);
// 两个方法的地址
Method originalMethod = class_getClassMethod(class, originalSelector);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
Method originalMethod1 = class_getClassMethod(class, originalSelector1);
Method swizzledMethod1 = class_getClassMethod(class, swizzledSelector1);
// 动态添加方法
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
BOOL didAddMethod1 =
class_addMethod(class,
originalSelector1,
method_getImplementation(swizzledMethod1),
method_getTypeEncoding(swizzledMethod1));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
if (didAddMethod1) {
class_replaceMethod(class,
swizzledSelector1,
method_getImplementation(originalMethod1),
method_getTypeEncoding(originalMethod1));
} else {
method_exchangeImplementations(originalMethod1, swizzledMethod1);
}
});
}
+ (UIFont *)tc_systemFontOfSize:(CGFloat)fontSize {
UIFont *newFont = nil;
newFont = [UIFont tc_systemFontOfSize:fontSize * Scaling];
return newFont;
}
+ (UIFont *)tc_fontWithName:(NSString *)fontName size:(CGFloat)fontSize {
UIFont *newFont = nil;
newFont = [UIFont tc_fontWithName:fontName size:fontSize * Scaling];
return newFont;
}
@end
xib适配
#import "UILabel+ScaleAdapter.h"
#import <objc/runtime.h>
//UI设计图宽度
#define DesignWidth 414.0
//缩放比例
#define Scaling ((CGFloat)([UIScreen mainScreen].bounds.size.width / DesignWidth))
@implementation UILabel (ScaleAdapter)
// 利用runtime机制,在load方法中实现让 jx_awakeFromNib 和 awakeFromNib 方法交换
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//要特别注意你替换的方法到底是哪个性质的方法(实例方法:Class class = [self class]; 类方法:Class class = object_getClass((id)self);)
//类方法的写法
Class class = [self class];
// 获取系统的selector
SEL originalSelector = @selector(awakeFromNib);
// 自己要交换的selector
SEL swizzledSelector = @selector(tc_awakeFromNib);
// 两个方法的地址
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
// 动态添加方法
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)tc_awakeFromNib {
[self tc_awakeFromNib];
self.font = [UIFont fontWithDescriptor:self.font.fontDescriptor size:self.font.pointSize * Scaling];
}
@end
注意:
关于宏定义中的DesignWidth,由于每人情况不同,请自行修改使用
[git链接]https://github.com/tcgitios/UILabelScaleAdapter
网友评论