cdts/xdts-ios 3/TreeHole/CYHResetCode/CYH/QMUIKit/QMUIComponents/QMUIAppearance.m
2023-07-27 09:20:00 +08:00

81 lines
3.6 KiB
Objective-C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Tencent is pleased to support the open source community by making QMUI_iOS available.
* Copyright (C) 2016-2021 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
//
// QMUIAppearance.m
// QMUIKit
//
// Created by MoLice on 2020/3/25.
//
#import "QMUIAppearance.h"
#import "QMUICore.h"
#import "QMUIWeakObjectContainer.h"
@implementation QMUIAppearance
static NSMutableDictionary *appearances;
+ (id)appearanceForClass:(Class)aClass {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!appearances) {
appearances = NSMutableDictionary.new;
}
});
NSString *className = NSStringFromClass(aClass);
id appearance = appearances[className];
if (!appearance) {
BeginIgnorePerformSelectorLeaksWarning
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"_%@:%@:", @"appearanceForClass", @"withContainerList"]);
appearance = [NSClassFromString(@"_UIAppearance") performSelector:selector withObject:aClass withObject:nil];
appearances[className] = appearance;
EndIgnorePerformSelectorLeaksWarning
}
return appearance;
}
@end
BeginIgnoreClangWarning(-Wincomplete-implementation)
@interface NSObject (QMUIAppearance_Private)
@property(nonatomic, assign) BOOL qmui_applyingAppearance;
+ (instancetype)appearance;
@end
@implementation NSObject (QMUIAppearnace)
QMUISynthesizeBOOLProperty(qmui_applyingAppearance, setQmui_applyingAppearance)
/**
关于 appearance 要考虑这几点:
1. 是否产生内存泄漏
2. 父类的 appearance 能否在子类里生效
3. 如果某个 property 在 ClassA 里声明为 UI_APPEARANCE_SELECTOR则在子类 Class B : Class A 里获取该 property 的值将为 nil这是正常的系统默认行为如此系统是在应用 appearance 的时候发现子类的 property 值为 nil 时才会从父类里读取值,在这个阶段才完成继承效果。
*/
- (void)qmui_applyAppearance {
Class class = self.class;
if ([class respondsToSelector:@selector(appearance)]) {
// -[_UIAppearance _applyInvocationsTo:window:] 会调用 _appearanceGuideClass如果不是 UIView 或者 UIViewController 的子类,需要额外实现这个方法。
SEL appearanceGuideClassSelector = NSSelectorFromString(@"_appearanceGuideClass");
if (!class_respondsToSelector(class, appearanceGuideClassSelector)) {
const char * typeEncoding = method_getTypeEncoding(class_getInstanceMethod(UIView.class, appearanceGuideClassSelector));
class_addMethod(class, appearanceGuideClassSelector, imp_implementationWithBlock(^Class(void) {
return nil;
}), typeEncoding);
}
self.qmui_applyingAppearance = YES;
BeginIgnorePerformSelectorLeaksWarning
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"_%@:%@:", @"applyInvocationsTo", @"window"]);
[NSClassFromString(@"_UIAppearance") performSelector:selector withObject:self withObject:nil];
EndIgnorePerformSelectorLeaksWarning
self.qmui_applyingAppearance = NO;
}
}
@end
EndIgnoreClangWarning