假设我们有这样一个需求,iPhone 6(屏幕宽度为375pt)上的设计图上的字号为17pt,iPhone 6 Plus上的字号根据屏幕宽度缩放,即字号为(17pt x 414pt / 375pt)= 18.768pt
创新互联公司专注于企业营销型网站、网站重做改版、海拉尔网站定制设计、自适应品牌网站建设、HTML5、商城网站开发、集团公司官网建设、外贸营销网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为海拉尔等各大城市提供网站开发制作服务。如果一个一个设置太麻烦,容易遗漏,这时候我们采用 runtime 的替换方法来实现,如果嫌替换方法太麻烦,我们可以用第三方库 Aspects 来辅助我们解决。
步骤:
添加pod
pod 'Aspects', '~> 1.4.1'
#import
NS_ASSUME_NONNULL_BEGIN
@interface UILabel (AspectsScaling)
@end
NS_ASSUME_NONNULL_END
UILabel+AspectsScaling.m 文件
#import "UILabel+AspectsScaling.h"
#import "Aspects.h"
@implementation UILabel (AspectsScaling)
+ (void)load {
NSError * error = nil;
[self aspect_hookSelector:@selector(initWithCoder:) withOptions:AspectPositionAfter usingBlock:^(id info, NSCoder * coder) {
[info.instance scaleFont];
} error:&error];
[self aspect_hookSelector:@selector(initWithFrame:) withOptions:AspectPositionAfter usingBlock:^(id info, CGRect frame) {
[info.instance scaleFont];
} error:&error];
//以下是log方法,可以不要
#if DEBUG
[self aspect_hookSelector:@selector(scaleFont) withOptions:AspectPositionBefore usingBlock:^(id info) {
UILabel * label = info.instance;
NSLog(@"UILabel: Before Scaling font size: %f", label.font.pointSize);
} error:&error];
[self aspect_hookSelector:@selector(scaleFont) withOptions:AspectPositionAfter usingBlock:^(id info) {
UILabel * label = info.instance;
NSLog(@"UILabel: After Scaling font size: %f", label.font.pointSize);
} error:&error];
#endif
}
- (void)scaleFont {
CGFloat ratio = CGRectGetWidth(UIScreen.mainScreen.bounds) / (CGFloat)375;
self.font = [UIFont fontWithDescriptor:self.font.fontDescriptor size:self.font.pointSize * ratio];
}
@end
- (void)scaleFont;
[self aspect_hookSelector:@selector(initWithCoder:) withOptions:AspectPositionAfter usingBlock:^(id info, NSCoder * coder)...
[self aspect_hookSelector:@selector(scaleFont) withOptions:AspectPositionBefore usingBlock:^(id info) ...
[self aspect_hookSelector:@selector(scaleFont) withOptions:AspectPositionAfter usingBlock:^(id info) ...
...
typedef NS_OPTIONS(NSUInteger, AspectOptions) {
AspectPositionAfter = 0, /// Called after the original implementation (default)
AspectPositionInstead = 1, /// Will replace the original implementation.
AspectPositionBefore = 2, /// Called before the original implementation.
AspectOptionAutomaticRemoval = 1 << 3 /// Will remove the hook after the first execution.
};
...
+ (id)aspect_hookSelector:(SEL)selector
withOptions:(AspectOptions)options
usingBlock:(id)block
error:(NSError **)error;
/// Adds a block of code before/instead/after the current `selector` for a specific instance.
- (id)aspect_hookSelector:(SEL)selector
withOptions:(AspectOptions)options
usingBlock:(id)block
error:(NSError **)error;
...
Aspects 是 iOS Aspect-oriented programming (AOP) 的一种实现,
满足以下几点就可以使用(但不是必须满足才能使用)
[UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(id aspectInfo, BOOL animated) {
NSLog(@"View Controller %@ will appear animated: %tu", aspectInfo.instance, animated);
} error:NULL];
Aspects 不是万能的,GitHub项目主页有Compatibility and Limitations ,一种常见的问题是当拦截一个方法的时候,它会把相关类当作已拦截,就会报错(A method can only be hooked once per class hierarchy ),所以当方法名相同时要考虑其他方法,这个 Aspects 库无法满足需求
另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。