针对整个项目改变font字体大小,设置大中小整体改变功能

谢奕
2023-12-01

使用分类通过runtime使用方法替换功能

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (Category)

/**
 @brief 方法替换
 @param originselector 替换的原方法
 @param swizzleSelector 替换后的方法
 @param isClassMethod 是否为类方法,YES为类方法,NO为对象方法
 */
+ (void)runtimeReplaceFunctionWithSelector:(SEL)originselector
                           swizzleSelector:(SEL)swizzleSelector
                             isClassMethod:(BOOL)isClassMethod;

@end

NS_ASSUME_NONNULL_END
#import "NSObject+Category.h"
#import <objc/runtime.h>
@implementation NSObject (Category)


/**
 @brief 方法替换
 @param originselector 替换的原方法
 @param swizzleSelector 替换后的方法
 @param isClassMethod 是否为类方法,YES为类方法,NO为对象方法
 */
+ (void)runtimeReplaceFunctionWithSelector:(SEL)originselector
                           swizzleSelector:(SEL)swizzleSelector
                             isClassMethod:(BOOL)isClassMethod
{
    Method originMethod;
    Method swizzleMethod;
    if (isClassMethod == YES) {
        originMethod = class_getClassMethod([self class], originselector);
        swizzleMethod = class_getClassMethod([self class], swizzleSelector);
    }else{
        originMethod = class_getInstanceMethod([self class], originselector);
        swizzleMethod = class_getInstanceMethod([self class], swizzleSelector);
    }
    method_exchangeImplementations(originMethod, swizzleMethod);
}

@end

针对UIFont UIlabel UIButton UITextView UITextField 写分类

#import "UIFont+Category.h"
#import "NSObject+Category.h"

@implementation UIFont (Category)

//+(void)load方法会在main函数之前自动调用,不需要手动调用
+ (void)load
{
    //交换systemFontOfSize: 方法
    [[self class] runtimeReplaceFunctionWithSelector:@selector(systemFontOfSize:) swizzleSelector:@selector(customSystemFontOfSize:) isClassMethod:YES];
    //交换fontWithName:size:方法
    [[self class] runtimeReplaceFunctionWithSelector:@selector(fontWithName:size:) swizzleSelector:@selector(customFontWithName:size:) isClassMethod:YES];
    
    //交换systemFontOfSize:weight:方法
    [[self class] runtimeReplaceFunctionWithSelector:@selector(systemFontOfSize:weight:) swizzleSelector:@selector(customSystemWeightFontOfSize:weight:) isClassMethod:YES];
}

//自定义的交换方法
+ (UIFont *)customSystemFontOfSize:(CGFloat)fontSize
{
    CGFloat size = [UIFont transSizeWithFontSize:fontSize];
    ///这里并不会引起递归,方法交换后,此时调用customSystemFontOfSize方法,其实是调用了原来的systemFontOfSize方法
    return [UIFont customSystemFontOfSize:size];
}

//自定义的交换方法
+ (UIFont *)customSystemWeightFontOfSize:(CGFloat)fontSize weight:(UIFontWeight)weightName
{
    CGFloat size = [UIFont transSizeWithFontSize:fontSize];
    ///这里并不会引起递归,方法交换后,此时调用customSystemFontOfSize方法,其实是调用了原来的systemFontOfSize方法
    return [UIFont customSystemWeightFontOfSize:size weight:weightName];
}

//自定义的交换方法
+ (UIFont *)customFontWithName:(NSString *)fontName size:(CGFloat)fontSize
{
    CGFloat size = [UIFont transSizeWithFontSize:fontSize];
    return [UIFont customFontWithName:fontName size:size];
}

/// 根据设置的大 中 小  对原有字体大小进行处理
+ (CGFloat)transSizeWithFontSize:(CGFloat)fontSize
{
    CGFloat size = fontSize;
    NSString *sizeFont = [kMyUserDefult objectForKey:@"setSizeFontData"];
    if ([sizeFont isEqualToString:@"大"]) {
        size += 2;
    }else if ([sizeFont isEqualToString:@"小"]){
        size -= 2;
    }
    return size;
}


@end
#import "UILabel+Category.h"
#import "NSObject+Category.h"

@implementation UILabel (Category)

+ (void)load
{
    [[self class] runtimeReplaceFunctionWithSelector:@selector(initWithCoder:) swizzleSelector:@selector(customInitWithCoder:) isClassMethod:NO];
}

- (instancetype)customInitWithCoder:(NSCoder *)coder
{
    if ([self customInitWithCoder:coder]) {
        ///此时调用fontWithName:size:方法,实际上调用的是方法交换后的customFontWithName:size:
        self.font = [UIFont fontWithName:self.font.familyName size:self.font.pointSize];
    }
    return self;
}

@end
#import "UIButton+Category.h"
#import "NSObject+Category.h"

@implementation UIButton (Category)

+ (void)load
{
    [[self class] runtimeReplaceFunctionWithSelector:@selector(initWithCoder:) swizzleSelector:@selector(customInitWithCoder:) isClassMethod:NO];
}

- (instancetype)customInitWithCoder:(NSCoder *)coder
{
    if ([self customInitWithCoder:coder]) {
        if (self.titleLabel != nil) {
            self.titleLabel.font = [UIFont fontWithName:self.titleLabel.font.familyName size:self.titleLabel.font.pointSize];
        }
    }
    return self;
}

@end
#import "UITextField+Category.h"
#import "NSObject+Category.h"

@implementation UITextField (Category)

+ (void)load
{
    [[self class] runtimeReplaceFunctionWithSelector:@selector(initWithCoder:) swizzleSelector:@selector(customInitWithCoder:) isClassMethod:NO];
}

- (instancetype)customInitWithCoder:(NSCoder *)coder
{
    if ([self customInitWithCoder:coder]) {
        self.font = [UIFont fontWithName:self.font.familyName size:self.font.pointSize];
    }
    return self;
}


@end
#import "UITextView+Category.h"
#import "NSObject+Category.h"

@implementation UITextView (Category)

+ (void)load
{
    [[self class] runtimeReplaceFunctionWithSelector:@selector(initWithCoder:) swizzleSelector:@selector(customInitWithCoder:) isClassMethod:NO];
}

- (instancetype)customInitWithCoder:(NSCoder *)coder
{
    if ([self customInitWithCoder:coder]) {
        self.font = [UIFont fontWithName:self.font.familyName size:self.font.pointSize];
    }
    return self;
}

@end

打开APP 会根据设置的大中小进行处理字体。

如果需要根据设置界面设置大中小进行改变的话,需要在一级界面注册相同的通知,在设置界面改变大中小后发送通知

    [kMyUserDefult setObject:sizeFont forKey:@"setSizeFontData"];
    [[NSNotificationCenter defaultCenter] postNotificationName:REFRESH_SIZEFONT_DATA object:nil];
    [tableView reloadData];

在所有的一级界面接收到通知的方法需要刷新整个界面,如果是列表可以直接刷新,如果不是列表 需要刷新指定view的font ,不是一级界面不需要刷新font,因为进入不是一级界面会走分类的+load方法,会走方法替换功能

一级界面如果是xib 把指定的 UIlabel UIButton UITextView UITextField  线拉出来,设置font,到时候刷新的话可以重新刷新到,进行改变font的值。

设置界面修改大中小字体时,一级界面和设置大中小界面 需要刷新view 让他重新走设置font值,其他都不用动,其他界面会走+load方法

 类似资料: