Fix a potential crash (#30)
This commit is contained in:
Родитель
9ab5b9031e
Коммит
84d459e9b5
|
@ -18,6 +18,8 @@
|
|||
8CAFD9E723716054001A63B8 /* DarkModeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C1915CE2361EFDB004A606A /* DarkModeKit.framework */; };
|
||||
8CAFD9E823716054001A63B8 /* DarkModeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8C1915CE2361EFDB004A606A /* DarkModeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
8CAFD9ED2371606D001A63B8 /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CAFD9EC2371606D001A63B8 /* NavigationController.swift */; };
|
||||
8CB63E41238551F3008ABCE2 /* UIView+DarkModeKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CB63E3F238551F3008ABCE2 /* UIView+DarkModeKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8CB63E42238551F3008ABCE2 /* UIView+DarkModeKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CB63E40238551F3008ABCE2 /* UIView+DarkModeKit.m */; };
|
||||
8CDA628C2366DAA9004895B5 /* DarkModeKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CDA62702366DAA9004895B5 /* DarkModeKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8CDA628D2366DAA9004895B5 /* DMTraitCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CDA62712366DAA9004895B5 /* DMTraitCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8CDA628E2366DAA9004895B5 /* DMTraitCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CDA62722366DAA9004895B5 /* DMTraitCollection.m */; };
|
||||
|
@ -91,6 +93,8 @@
|
|||
8CAFD9E023715FAB001A63B8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
8CAFD9E223715FAB001A63B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
8CAFD9EC2371606D001A63B8 /* NavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = "<group>"; };
|
||||
8CB63E3F238551F3008ABCE2 /* UIView+DarkModeKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+DarkModeKit.h"; sourceTree = "<group>"; };
|
||||
8CB63E40238551F3008ABCE2 /* UIView+DarkModeKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+DarkModeKit.m"; sourceTree = "<group>"; };
|
||||
8CDA62702366DAA9004895B5 /* DarkModeKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DarkModeKit.h; sourceTree = "<group>"; };
|
||||
8CDA62712366DAA9004895B5 /* DMTraitCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DMTraitCollection.h; sourceTree = "<group>"; };
|
||||
8CDA62722366DAA9004895B5 /* DMTraitCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DMTraitCollection.m; sourceTree = "<group>"; };
|
||||
|
@ -175,6 +179,8 @@
|
|||
8CDA62722366DAA9004895B5 /* DMTraitCollection.m */,
|
||||
8C071AEA23683BF5001AB7B2 /* NSObject+DarkModeKit.h */,
|
||||
8C071AEB23683BF5001AB7B2 /* NSObject+DarkModeKit.m */,
|
||||
8CB63E3F238551F3008ABCE2 /* UIView+DarkModeKit.h */,
|
||||
8CB63E40238551F3008ABCE2 /* UIView+DarkModeKit.m */,
|
||||
);
|
||||
path = DarkModeCore;
|
||||
sourceTree = "<group>";
|
||||
|
@ -272,6 +278,7 @@
|
|||
8C071AEC23683BF5001AB7B2 /* NSObject+DarkModeKit.h in Headers */,
|
||||
8CDA628D2366DAA9004895B5 /* DMTraitCollection.h in Headers */,
|
||||
8CDA628C2366DAA9004895B5 /* DarkModeKit.h in Headers */,
|
||||
8CB63E41238551F3008ABCE2 /* UIView+DarkModeKit.h in Headers */,
|
||||
8CDA62912366DAA9004895B5 /* DMDynamicImage.h in Headers */,
|
||||
8CDA62A52366DAA9004895B5 /* DMDynamicColor.h in Headers */,
|
||||
);
|
||||
|
@ -409,6 +416,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8CDA62972366DAA9004895B5 /* UIScrollView+Theme.swift in Sources */,
|
||||
8CB63E42238551F3008ABCE2 /* UIView+DarkModeKit.m in Sources */,
|
||||
8CDA62A12366DAA9004895B5 /* UITextField+Theme.swift in Sources */,
|
||||
8CDA62952366DAA9004895B5 /* UIWindow+Theme.swift in Sources */,
|
||||
8CDA629E2366DAA9004895B5 /* UIViewController+Theme.swift in Sources */,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#import <DarkModeKit/DMDynamicImage.h>
|
||||
#import <DarkModeKit/DMTraitCollection.h>
|
||||
#import <DarkModeKit/NSObject+DarkModeKit.h>
|
||||
#import <DarkModeKit/UIView+DarkModeKit.h>
|
||||
|
||||
//! Project version number for DarkModeKit.
|
||||
FOUNDATION_EXPORT double DarkModeKitVersionNumber;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class DMDynamicColor;
|
||||
|
||||
@interface UIView (DarkModeKit)
|
||||
|
||||
+ (void)dm_swizzleSetBackgroundColor;
|
||||
|
||||
@property (nonatomic, copy, nullable) DMDynamicColor *dm_dynamicBackgroundColor;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
#import "UIView+DarkModeKit.h"
|
||||
#import "DMDynamicColor.h"
|
||||
|
||||
@import ObjectiveC;
|
||||
|
||||
@implementation UIView (DarkModeKit)
|
||||
|
||||
static void (*dm_original_setBackgroundColor)(UIView *, SEL, UIColor *);
|
||||
|
||||
static void dm_setBackgroundColor(UIView *self, SEL _cmd, UIColor *color) {
|
||||
if ([color isKindOfClass:[DMDynamicColor class]]) {
|
||||
self.dm_dynamicBackgroundColor = (DMDynamicColor *)color;
|
||||
} else {
|
||||
self.dm_dynamicBackgroundColor = nil;
|
||||
}
|
||||
dm_original_setBackgroundColor(self, _cmd, color);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/42677534/swizzling-on-properties-that-conform-to-ui-appearance-selector
|
||||
+ (void)dm_swizzleSetBackgroundColor {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
Method method = class_getInstanceMethod(self, @selector(setBackgroundColor:));
|
||||
dm_original_setBackgroundColor = (void *)method_getImplementation(method);
|
||||
method_setImplementation(method, (IMP)dm_setBackgroundColor);
|
||||
});
|
||||
}
|
||||
|
||||
- (DMDynamicColor *)dm_dynamicBackgroundColor {
|
||||
return objc_getAssociatedObject(self, _cmd);
|
||||
}
|
||||
|
||||
- (void)setDm_dynamicBackgroundColor:(DMDynamicColor *)dm_dynamicBackgroundColor {
|
||||
objc_setAssociatedObject(self,
|
||||
@selector(dm_dynamicBackgroundColor),
|
||||
dm_dynamicBackgroundColor,
|
||||
OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
}
|
||||
|
||||
@end
|
|
@ -38,7 +38,7 @@ public final class DarkModeManager: NSObject {
|
|||
|
||||
// Colors
|
||||
UIView.swizzleWillMoveToWindowOnce
|
||||
UIView.swizzleSetBackgroundColorOnce
|
||||
UIView.dm_swizzleSetBackgroundColor()
|
||||
UIView.swizzleSetTintColorOnce
|
||||
UITextField.swizzleTextFieldWillMoveToWindowOnce
|
||||
UILabel.swizzleDidMoveToWindowOnce
|
||||
|
|
|
@ -17,7 +17,7 @@ extension UIView: Themeable {
|
|||
}
|
||||
|
||||
@objc func _updateDynamicColors() {
|
||||
if let dynamicBackgroundColor = _dynamicBackgroundColor {
|
||||
if let dynamicBackgroundColor = dm_dynamicBackgroundColor {
|
||||
backgroundColor = dynamicBackgroundColor
|
||||
}
|
||||
if let dynamicTintColor = _dynamicTintColor {
|
||||
|
@ -48,37 +48,20 @@ extension UIView {
|
|||
|
||||
extension UIView {
|
||||
private struct Constants {
|
||||
static var dynamicBackgroundColorKey = "dynamicBackgroundColorKey"
|
||||
static var dynamicTintColorKey = "dynamicTintColorKey"
|
||||
}
|
||||
|
||||
static let swizzleSetBackgroundColorOnce: Void = {
|
||||
if !dm_swizzleInstanceMethod(#selector(setter: backgroundColor), to: #selector(outlookSetBackgroundColor)) {
|
||||
assertionFailure(DarkModeManager.messageForSwizzlingFailed(class: UIView.self, selector: #selector(setter: backgroundColor)))
|
||||
}
|
||||
}()
|
||||
|
||||
static let swizzleSetTintColorOnce: Void = {
|
||||
if !dm_swizzleInstanceMethod(#selector(setter: tintColor), to: #selector(outlookSetTintColor)) {
|
||||
assertionFailure(DarkModeManager.messageForSwizzlingFailed(class: UIView.self, selector: #selector(setter: tintColor)))
|
||||
}
|
||||
}()
|
||||
|
||||
private var _dynamicBackgroundColor: DynamicColor? {
|
||||
get { return objc_getAssociatedObject(self, &Constants.dynamicBackgroundColorKey) as? DynamicColor }
|
||||
set { objc_setAssociatedObject(self, &Constants.dynamicBackgroundColorKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) }
|
||||
}
|
||||
|
||||
private var _dynamicTintColor: DynamicColor? {
|
||||
get { return objc_getAssociatedObject(self, &Constants.dynamicTintColorKey) as? DynamicColor }
|
||||
set { objc_setAssociatedObject(self, &Constants.dynamicTintColorKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) }
|
||||
}
|
||||
|
||||
@objc private dynamic func outlookSetBackgroundColor(_ color: UIColor) {
|
||||
_dynamicBackgroundColor = color as? DynamicColor
|
||||
outlookSetBackgroundColor(color)
|
||||
}
|
||||
|
||||
@objc private dynamic func outlookSetTintColor(_ color: UIColor) {
|
||||
_dynamicTintColor = color as? DynamicColor
|
||||
outlookSetTintColor(color)
|
||||
|
|
|
@ -6,4 +6,10 @@
|
|||
import XCTest
|
||||
@testable import DarkModeKit
|
||||
|
||||
final class DarkModeKitTests: XCTestCase {}
|
||||
final class DarkModeKitTests: XCTestCase {
|
||||
func testSetBackgroundColorSwizzling() {
|
||||
UIWindow.appearance().backgroundColor = .white
|
||||
DarkModeManager.setup(updateAppearance: { _ in })
|
||||
_ = UIWindow()
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче