Browse Source

【功能】增加字体适配

xcbosa mbp16 1 year ago
parent
commit
51c1fe9350

+ 4 - 0
XCTheme/Classes/Business/FontScale/XCFontScale.h

@@ -9,6 +9,9 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+extern const NSString *const kXCFontScaleBeforeChangeNotificationKey;
+extern const NSString *const kXCFontScaleAfterChangeNotificationKey;
+
 @interface XCFontScale : NSObject
 
 @property (nonatomic, strong, readonly, class) XCFontScale *shared;
@@ -20,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
 - (UIFont *)fontWithFactor:(UIFont *)font;
 
 - (void)registerTarget:(NSObject *)target fontSizeChangeBlock:(nullable void (^)(XCFontScale *))block;
+- (void)replaceTarget:(NSObject *)target fontSizeChangeBlock:(nullable void (^)(XCFontScale *))block;
 
 - (void)sendFontSizeChangeNotificationToObservers;
 

+ 27 - 0
XCTheme/Classes/Business/FontScale/XCFontScale.m

@@ -6,6 +6,10 @@
 //
 
 #import "XCFontScale.h"
+#import <XCNotificationCenter/XCNotificationCenter-umbrella.h>
+
+const NSString *const kXCFontScaleBeforeChangeNotificationKey = @"XCFontScaleBeforeChangeNotificationKey";
+const NSString *const kXCFontScaleAfterChangeNotificationKey = @"XCFontScaleAfterChangeNotificationKey";
 
 @interface XCFontScaleChangeBlock : NSObject
 
@@ -68,6 +72,9 @@ NSString *const kXCFontScaleFactorKey = @"factor";
 }
 
 - (void)registerTarget:(NSObject *)target fontSizeChangeBlock:(nullable void (^)(XCFontScale *))block {
+    if (!target) {
+        return;
+    }
     XCFontScaleChangeBlock *changeBlock = [XCFontScaleChangeBlock new];
     changeBlock.weakObject = target;
     changeBlock.block = block;
@@ -76,6 +83,23 @@ NSString *const kXCFontScaleFactorKey = @"factor";
     [self.fontSizeChangeObserverLock unlock];
 }
 
+- (void)replaceTarget:(NSObject *)target fontSizeChangeBlock:(nullable void (^)(XCFontScale *))block {
+    if (!target) {
+        return;
+    }
+    XCFontScaleChangeBlock *changeBlock = [XCFontScaleChangeBlock new];
+    changeBlock.weakObject = target;
+    changeBlock.block = block;
+    [self.fontSizeChangeObserverLock lock];
+    for (XCFontScaleChangeBlock *block in [self.fontSizeObservers copy]) {
+        if (block.weakObject == nil || block.weakObject == target) {
+            [self.fontSizeObservers removeObject:block];
+        }
+    }
+    [self.fontSizeObservers addObject:changeBlock];
+    [self.fontSizeChangeObserverLock unlock];
+}
+
 - (void)sendFontSizeChangeNotificationToObservers {
     [self.fontSizeChangeObserverLock lock];
     NSArray *observers = [self.fontSizeObservers copy];
@@ -94,9 +118,12 @@ NSString *const kXCFontScaleFactorKey = @"factor";
     }
     [self.fontSizeObservers removeObjectsAtIndexes:[indexNeedToRemoval copy]];
     [self.fontSizeChangeObserverLock unlock];
+    
+    [XCOCNotificationCenter.shared postNotificationNamed:kXCFontScaleBeforeChangeNotificationKey attachedObject:self];
     for (void (^block)(XCFontScale *) in needCallBlocks) {
         block(self);
     }
+    [XCOCNotificationCenter.shared postNotificationNamed:kXCFontScaleAfterChangeNotificationKey attachedObject:self];
 }
 
 - (NSUserDefaults *)storage {

+ 23 - 2
XCTheme/Classes/Business/FontScale/XCFontScaleCategory.h

@@ -6,12 +6,33 @@
 //
 
 #import <Foundation/Foundation.h>
+#import <YYText/YYText.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface UIView (XCFontScaleCategory)
+@protocol XCFontScaleView <NSObject>
 
-@property (nonatomic, assign) BOOL enableAutoFontScale;
+/// 获取或设置动态缩放字体
+@property (nonatomic, strong) UIFont *autoScaleFont;
+
+/// 如果设置了autoScaleFont,则当字体大小变化时会调用此block
+@property (nonatomic, copy, nullable) void (^fontSizeChangedBlock)(void);
+
+@end
+
+@interface UILabel (XCFontScaleCategory) <XCFontScaleView>
+
+@end
+
+@interface UITextView (XCFontScaleCategory) <XCFontScaleView>
+
+@end
+
+@interface YYLabel (XCFontScaleCategory) <XCFontScaleView>
+
+@end
+
+@interface YYTextView (XCFontScaleCategory) <XCFontScaleView>
 
 @end
 

+ 107 - 75
XCTheme/Classes/Business/FontScale/XCFontScaleCategory.m

@@ -8,88 +8,120 @@
 #import "XCFontScaleCategory.h"
 #import <XCPublicModule/XCPublicModule.h>
 #import "XCFontScale.h"
-#import <YYText/YYText.h>
 
-@implementation UIView (XCFontScaleCategory)
+#define InvokeFontSizeChangeBlock void (^fontSizeChangeBlock)(void) = self.fontSizeChangedBlock; \
+    if (fontSizeChangeBlock) { \
+        fontSizeChangeBlock(); \
+    }
+
+@implementation UILabel (XCFontScaleCategory)
+
+- (UIFont *)autoScaleFont {
+    return objc_getAssociatedObject(self, @selector(autoScaleFont));
+}
+
+- (void)setAutoScaleFont:(UIFont *)autoScaleFont {
+    objc_setAssociatedObject(self, @selector(autoScaleFont), autoScaleFont, OBJC_ASSOCIATION_RETAIN);
+    self.font = [XCFontScale.shared fontWithFactor:autoScaleFont];
+    InvokeFontSizeChangeBlock;
+    XC_WEAKIFY_SELF;
+    [XCFontScale.shared replaceTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
+        XC_STRONG_SELF;
+        self.font = [fontScale fontWithFactor:autoScaleFont];
+        InvokeFontSizeChangeBlock;
+    }];
+}
 
-- (BOOL)enableAutoFontScale {
-    return objc_getAssociatedObject(self, @selector(enableAutoFontScale));
+- (void (^)(void))fontSizeChangedBlock {
+    return objc_getAssociatedObject(self, @selector(fontSizeChangedBlock));
 }
 
-- (void)setEnableAutoFontScale:(BOOL)enableAutoFontScale {
-    objc_setAssociatedObject(self, @selector(enableAutoFontScale), (__bridge id _Nullable)((void *)enableAutoFontScale), OBJC_ASSOCIATION_ASSIGN);
+- (void)setFontSizeChangedBlock:(void (^)(void))fontSizeChangedBlock {
+    objc_setAssociatedObject(self, @selector(fontSizeChangedBlock), fontSizeChangedBlock, OBJC_ASSOCIATION_COPY);
 }
 
 @end
 
-begin_override(HookUILabelFont, UILabel, setFont:, void, setFont:(UIFont *)font) {
-    SEL selector = @selector(swizzled_setFont:);
-    IMP imp = class_getMethodImplementation([UILabel class], selector);
-    void (*method)(id, SEL, UIFont *) = (void *)imp;
-    if (self.enableAutoFontScale) {
-        UIFont *capturedFont = [font copy];
-        method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-        XC_WEAKIFY_SELF;
-        [XCFontScale.shared registerTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
-            XC_STRONG_SELF;
-            method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-        }];
-    } else {
-        method(self, selector, font);
-    }
+@implementation UITextView (XCFontScaleCategory)
+
+- (UIFont *)autoScaleFont {
+    return objc_getAssociatedObject(self, @selector(autoScaleFont));
 }
-end_override;
-
-begin_override(HookYYLabelFont, YYLabel, setFont:, void, setFont:(UIFont *)font) {
-    SEL selector = @selector(swizzled_setFont:);
-    IMP imp = class_getMethodImplementation([UILabel class], selector);
-    void (*method)(id, SEL, UIFont *) = (void *)imp;
-    if (self.enableAutoFontScale) {
-        UIFont *capturedFont = [font copy];
-        method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-        XC_WEAKIFY_SELF;
-        [XCFontScale.shared registerTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
-            XC_STRONG_SELF;
-            method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-        }];
-    } else {
-        method(self, selector, font);
-    }
+
+- (void)setAutoScaleFont:(UIFont *)autoScaleFont {
+    objc_setAssociatedObject(self, @selector(autoScaleFont), autoScaleFont, OBJC_ASSOCIATION_RETAIN);
+    self.font = [XCFontScale.shared fontWithFactor:autoScaleFont];
+    InvokeFontSizeChangeBlock;
+    XC_WEAKIFY_SELF;
+    [XCFontScale.shared replaceTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
+        XC_STRONG_SELF;
+        self.font = [fontScale fontWithFactor:autoScaleFont];
+        InvokeFontSizeChangeBlock;
+    }];
+}
+
+- (void (^)(void))fontSizeChangedBlock {
+    return objc_getAssociatedObject(self, @selector(fontSizeChangedBlock));
+}
+
+- (void)setFontSizeChangedBlock:(void (^)(void))fontSizeChangedBlock {
+    objc_setAssociatedObject(self, @selector(fontSizeChangedBlock), fontSizeChangedBlock, OBJC_ASSOCIATION_COPY);
+}
+
+@end
+
+@implementation YYLabel (XCFontScaleCategory)
+
+- (UIFont *)autoScaleFont {
+    return objc_getAssociatedObject(self, @selector(autoScaleFont));
 }
-end_override;
-
-//begin_override(HookUITextView, UITextView, setFont:, void, setFont:(UIFont *)font) {
-//    SEL selector = @selector(swizzled_setFont:);
-//    IMP imp = class_getMethodImplementation([UILabel class], selector);
-//    void (*method)(id, SEL, UIFont *) = (void *)imp;
-//    if (self.enableAutoFontScale) {
-//        UIFont *capturedFont = [font copy];
-//        method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-//        XC_WEAKIFY_SELF;
-//        [XCFontScale.shared registerTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
-//            XC_STRONG_SELF;
-//            method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-//        }];
-//    } else {
-//        method(self, selector, font);
-//    }
-//}
-//end_override;
-
-//begin_override(HookYYTextView, YYTextView, setFont:, void, setFont:(UIFont *)font) {
-//    SEL selector = @selector(swizzled_setFont:);
-//    IMP imp = class_getMethodImplementation([UILabel class], selector);
-//    void (*method)(id, SEL, UIFont *) = (void *)imp;
-//    if (self.enableAutoFontScale) {
-//        UIFont *capturedFont = [font copy];
-//        method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-//        XC_WEAKIFY_SELF;
-//        [XCFontScale.shared registerTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
-//            XC_STRONG_SELF;
-//            method(self, selector, [XCFontScale.shared fontWithFactor:capturedFont]);
-//        }];
-//    } else {
-//        method(self, selector, font);
-//    }
-//}
-//end_override;
+
+- (void)setAutoScaleFont:(UIFont *)autoScaleFont {
+    objc_setAssociatedObject(self, @selector(autoScaleFont), autoScaleFont, OBJC_ASSOCIATION_RETAIN);
+    self.font = [XCFontScale.shared fontWithFactor:autoScaleFont];
+    InvokeFontSizeChangeBlock;
+    XC_WEAKIFY_SELF;
+    [XCFontScale.shared replaceTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
+        XC_STRONG_SELF;
+        self.font = [fontScale fontWithFactor:autoScaleFont];
+        InvokeFontSizeChangeBlock;
+    }];
+}
+
+- (void (^)(void))fontSizeChangedBlock {
+    return objc_getAssociatedObject(self, @selector(fontSizeChangedBlock));
+}
+
+- (void)setFontSizeChangedBlock:(void (^)(void))fontSizeChangedBlock {
+    objc_setAssociatedObject(self, @selector(fontSizeChangedBlock), fontSizeChangedBlock, OBJC_ASSOCIATION_COPY);
+}
+
+@end
+
+@implementation YYTextView (XCFontScaleCategory)
+
+- (UIFont *)autoScaleFont {
+    return objc_getAssociatedObject(self, @selector(autoScaleFont));
+}
+
+- (void)setAutoScaleFont:(UIFont *)autoScaleFont {
+    objc_setAssociatedObject(self, @selector(autoScaleFont), autoScaleFont, OBJC_ASSOCIATION_RETAIN);
+    self.font = [XCFontScale.shared fontWithFactor:autoScaleFont];
+    InvokeFontSizeChangeBlock;
+    XC_WEAKIFY_SELF;
+    [XCFontScale.shared replaceTarget:self fontSizeChangeBlock:^(XCFontScale * _Nonnull fontScale) {
+        XC_STRONG_SELF;
+        self.font = [fontScale fontWithFactor:autoScaleFont];
+        InvokeFontSizeChangeBlock;
+    }];
+}
+
+- (void (^)(void))fontSizeChangedBlock {
+    return objc_getAssociatedObject(self, @selector(fontSizeChangedBlock));
+}
+
+- (void)setFontSizeChangedBlock:(void (^)(void))fontSizeChangedBlock {
+    objc_setAssociatedObject(self, @selector(fontSizeChangedBlock), fontSizeChangedBlock, OBJC_ASSOCIATION_COPY);
+}
+
+@end