Tencent / QMUI_iOS

QMUI iOS——致力于提高项目 UI 开发效率的解决方案
http://qmuiteam.com/ios
Other
7.05k stars 1.37k forks source link

QMUITheme 跟随系统时切换异常 #1449

Closed 0x1306a94 closed 1 year ago

0x1306a94 commented 1 year ago

Bug 表现 颜色名称: B1 Light: 0xffffff Dark: 0x121212

BaseViewController viewDidLoad 中默认设置了 self.view.backgroundColor = B1 B页面不支持主题模式,所以在 viewDidLoad 中设置了self.view.backgroundColor = UIColorMake(0x12, 0x12, 0x12) 当主题模式设为跟随系统时, 在A页面后将系统dark mode开启, 然后pushB页面 进入B页面后颜色为0x121212正常, 此时将系统dark mode关闭后, B页面变成了0xffffff不正常

通过调试发现一个颜色在多次调用CGColor时会出现内存地址一样的情况

WechatIMG1402

继续分析发现在UIColor+QMUITheme.m

- (CGColorRef)CGColor {
    CGColorRef colorRef = [UIColor colorWithCGColor:self.qmui_rawColor.CGColor].CGColor;
    [(__bridge id)(colorRef) qmui_bindObject:self forKey:QMUICGColorOriginalColorBindKey];
    return colorRef;
}

CALayer (QMUIThemeCompatibility)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        OverrideImplementation([CALayer class], @selector(setBackgroundColor:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
            return ^(CALayer *selfObject, CGColorRef color) {

                // iOS 13 的 UIDynamicProviderColor,以及 QMUIThemeColor 在获取 CGColor 时会将自身绑定到 CGColorRef 上,这里把原始的 color 重新获取出来存到 property 里,以备样式更新时调用

                // 由于上面调试发现 CGColor 存在复用的情况, 所有这里还是能拿到之前关联的QMUIThemeColor
                // 然后就导致下面 qmui_setNeedsUpdateDynamicStyle 调用时,又被覆盖回去了
                UIColor *originalColor = [(__bridge id)(color) qmui_getBoundObjectForKey:QMUICGColorOriginalColorBindKey];
                selfObject.qcl_originalBackgroundColor = originalColor;

                // call super
                void (*originSelectorIMP)(id, SEL, CGColorRef);
                originSelectorIMP = (void (*)(id, SEL, CGColorRef))originalIMPProvider();
                originSelectorIMP(selfObject, originCMD, color);
            };
        });

    });
}

- (void)qmui_setNeedsUpdateDynamicStyle {
    if (self.qcl_originalBackgroundColor) {
        UIColor *originalColor = self.qcl_originalBackgroundColor;
        self.backgroundColor = originalColor.CGColor;
    }
}

截图

如何重现 复现QMUIThemeSample.zip

预期的表现 切换系统dark mode都应该是 0x121212

其他信息

MoLice commented 1 year ago

该问题在 #1463 里跟进

MoLice commented 1 year ago

已修复该问题,请根据 iOS 版本支持情况选择升级到 4.6.0(iOS 11-16)4.6.1(iOS 13-16)