diff --git a/FluentDarkModeKit.xcodeproj/project.pbxproj b/FluentDarkModeKit.xcodeproj/project.pbxproj index 9c7772b..ffb61e7 100644 --- a/FluentDarkModeKit.xcodeproj/project.pbxproj +++ b/FluentDarkModeKit.xcodeproj/project.pbxproj @@ -55,6 +55,7 @@ 8CE066D0239E5586002CE16D /* UIImage+DarkModeKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CC8D8722398E7A30043276A /* UIImage+DarkModeKit.m */; }; EA2EA50024A1CBF2001AE312 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA2EA4FE24A1CAD5001AE312 /* SceneDelegate.swift */; }; EA7316F1248F5055009AE037 /* UILabelVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7316EF248F5050009AE037 /* UILabelVC.swift */; }; + EAE6065624A9DA1B001304D1 /* UIImageViewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAE6065324A9D9E0001304D1 /* UIImageViewVC.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -149,6 +150,7 @@ 8CDA628B2366DAA9004895B5 /* DMDynamicColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DMDynamicColor.h; sourceTree = ""; }; EA2EA4FE24A1CAD5001AE312 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; EA7316EF248F5050009AE037 /* UILabelVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UILabelVC.swift; sourceTree = ""; }; + EAE6065324A9D9E0001304D1 /* UIImageViewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageViewVC.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -289,6 +291,7 @@ 8C63F64123A36B0900D93CF4 /* UIButtonVC.swift */, 8C63F64423A374CF00D93CF4 /* UIPageControlVC.swift */, EA7316EF248F5050009AE037 /* UILabelVC.swift */, + EAE6065324A9D9E0001304D1 /* UIImageViewVC.swift */, 8CAFD9DD23715FAB001A63B8 /* Assets.xcassets */, 8CAFD9DF23715FAB001A63B8 /* LaunchScreen.storyboard */, 8CAFD9E223715FAB001A63B8 /* Info.plist */, @@ -576,6 +579,7 @@ 8C7B250C23A22A80002E2558 /* UIActivityIndicatorViewVC.swift in Sources */, 8CAFD9D923715FAA001A63B8 /* ViewController.swift in Sources */, 8C63F64323A36B2700D93CF4 /* UIButtonVC.swift in Sources */, + EAE6065624A9DA1B001304D1 /* UIImageViewVC.swift in Sources */, EA7316F1248F5055009AE037 /* UILabelVC.swift in Sources */, 8CAFD9ED2371606D001A63B8 /* NavigationController.swift in Sources */, EA2EA50024A1CBF2001AE312 /* SceneDelegate.swift in Sources */, diff --git a/Sources/DarkModeCore/DMDynamicColor.m b/Sources/DarkModeCore/DMDynamicColor.m index 3722bf4..2d575a8 100644 --- a/Sources/DarkModeCore/DMDynamicColor.m +++ b/Sources/DarkModeCore/DMDynamicColor.m @@ -22,7 +22,7 @@ } - (UIColor *)resolvedColor { - return [self resolvedColorWithTraitCollection:DMTraitCollection.currentTraitCollection]; + return [self resolvedColorWithTraitCollection:DMTraitCollection.overrideTraitCollection]; } - (UIColor *)resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection { diff --git a/Sources/DarkModeCore/DMDynamicImage.m b/Sources/DarkModeCore/DMDynamicImage.m index e14c1a3..2f7e454 100644 --- a/Sources/DarkModeCore/DMDynamicImage.m +++ b/Sources/DarkModeCore/DMDynamicImage.m @@ -37,7 +37,7 @@ } - (UIImage *)resolvedImage { - if (DMTraitCollection.currentTraitCollection.userInterfaceStyle == DMUserInterfaceStyleDark) { + if (DMTraitCollection.overrideTraitCollection.userInterfaceStyle == DMUserInterfaceStyleDark) { return self.darkImage; } else { return self.lightImage; diff --git a/Sources/DarkModeCore/DMTraitCollection.h b/Sources/DarkModeCore/DMTraitCollection.h index e004958..655c817 100644 --- a/Sources/DarkModeCore/DMTraitCollection.h +++ b/Sources/DarkModeCore/DMTraitCollection.h @@ -17,7 +17,7 @@ typedef NS_ENUM(NSInteger, DMUserInterfaceStyle) { @interface DMTraitCollection : NSObject -@property (class, nonatomic, readonly) DMTraitCollection *currentTraitCollection; +@property (class, nonatomic, readonly) DMTraitCollection *currentTraitCollection API_DEPRECATED("Use overrideTraitCollection instead.", ios(11.0, 11.0)); @property (class, nonatomic, readonly) DMTraitCollection *overrideTraitCollection; + (DMTraitCollection *)traitCollectionWithUserInterfaceStyle:(DMUserInterfaceStyle)userInterfaceStyle; diff --git a/Sources/DarkModeCore/DMTraitCollection.m b/Sources/DarkModeCore/DMTraitCollection.m index a1c675d..135be0c 100644 --- a/Sources/DarkModeCore/DMTraitCollection.m +++ b/Sources/DarkModeCore/DMTraitCollection.m @@ -45,7 +45,7 @@ @implementation DMTraitCollection -static DMTraitCollection *_overrideTraitCollection = nil; // This is set manually in setCurrentTraitCollection:animated +static DMTraitCollection *_overrideTraitCollection = nil; // This is set manually in setOverrideTraitCollection:animated static void (^_userInterfaceStyleChangeHandler)(DMTraitCollection *, BOOL) = nil; static BOOL _isObservingNewWindowAddNotification = NO; @@ -68,8 +68,8 @@ static BOOL _isObservingNewWindowAddNotification = NO; return [DMTraitCollection traitCollectionWithUITraitCollection:UIScreen.mainScreen.traitCollection]; } -+ (void)setOverrideTraitCollection:(DMTraitCollection *)currentTraitCollection animated:(BOOL)animated { - _overrideTraitCollection = currentTraitCollection; ++ (void)setOverrideTraitCollection:(DMTraitCollection *)overrideTraitCollection animated:(BOOL)animated { + _overrideTraitCollection = overrideTraitCollection; [self syncImmediatelyAnimated:animated]; } diff --git a/Sources/DarkModeCore/UIImage+DarkModeKit.m b/Sources/DarkModeCore/UIImage+DarkModeKit.m index 289e6f3..fe538ae 100644 --- a/Sources/DarkModeCore/UIImage+DarkModeKit.m +++ b/Sources/DarkModeCore/UIImage+DarkModeKit.m @@ -5,6 +5,7 @@ #import "UIImage+DarkModeKit.h" #import "DMDynamicImage.h" +#import "DMTraitCollection.h" @import ObjectiveC; @@ -36,6 +37,22 @@ } + (UIImage *)dm_imageWithLightImage:(UIImage *)lightImage darkImage:(UIImage *)darkImage { + if (@available(iOS 13, *)) { + UIImageAsset *imageAsset = [[UIImageAsset alloc] init]; + + // Always specify a displayScale otherwise a default of 1.0 is assigned + [imageAsset registerImage:lightImage withTraitCollection:[UITraitCollection traitCollectionWithTraitsFromCollections:@[ + [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight], + [UITraitCollection traitCollectionWithDisplayScale:lightImage.scale] + ]]]; + [imageAsset registerImage:darkImage withTraitCollection:[UITraitCollection traitCollectionWithTraitsFromCollections:@[ + [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark], + [UITraitCollection traitCollectionWithDisplayScale:darkImage.scale] + ]]]; + + return [imageAsset imageWithTraitCollection:DMTraitCollection.overrideTraitCollection.uiTraitCollection]; + } + return (UIImage *)[[DMDynamicImageProxy alloc] initWithLightImage:lightImage darkImage:darkImage]; } diff --git a/Sources/FluentDarkModeKit/Extensions/UILabel+DarkModeKit.swift b/Sources/FluentDarkModeKit/Extensions/UILabel+DarkModeKit.swift index 1c21218..3ae26b0 100644 --- a/Sources/FluentDarkModeKit/Extensions/UILabel+DarkModeKit.swift +++ b/Sources/FluentDarkModeKit/Extensions/UILabel+DarkModeKit.swift @@ -19,8 +19,8 @@ extension UILabel { class_replaceMethod(UILabel.self, selector, imp_implementationWithBlock({ (self: UILabel) -> Void in let oldIMP = unsafeBitCast(imp, to: (@convention(c) (UILabel, Selector) -> Void).self) oldIMP(self, selector) - if self.currentUserInterfaceStyle != DMTraitCollection.current.userInterfaceStyle { - self.currentUserInterfaceStyle = DMTraitCollection.current.userInterfaceStyle + if self.currentUserInterfaceStyle != DMTraitCollection.override.userInterfaceStyle { + self.currentUserInterfaceStyle = DMTraitCollection.override.userInterfaceStyle self.dmTraitCollectionDidChange(nil) } } as @convention(block) (UILabel) -> Void), method_getTypeEncoding(method)) diff --git a/Sources/FluentDarkModeKit/Extensions/UIScrollView+DarkModeKit.swift b/Sources/FluentDarkModeKit/Extensions/UIScrollView+DarkModeKit.swift index e162822..5036c4f 100644 --- a/Sources/FluentDarkModeKit/Extensions/UIScrollView+DarkModeKit.swift +++ b/Sources/FluentDarkModeKit/Extensions/UIScrollView+DarkModeKit.swift @@ -14,7 +14,7 @@ extension UIScrollView { dm_updateDynamicColors() indicatorStyle = { - if DMTraitCollection.current.userInterfaceStyle == .dark { + if DMTraitCollection.override.userInterfaceStyle == .dark { return .white } else { diff --git a/Sources/FluentDarkModeKit/Extensions/UITextField+DarkModeKit.swift b/Sources/FluentDarkModeKit/Extensions/UITextField+DarkModeKit.swift index b3e297c..b021179 100644 --- a/Sources/FluentDarkModeKit/Extensions/UITextField+DarkModeKit.swift +++ b/Sources/FluentDarkModeKit/Extensions/UITextField+DarkModeKit.swift @@ -18,7 +18,7 @@ extension UITextField { } keyboardAppearance = { - if DMTraitCollection.current.userInterfaceStyle == .dark { + if DMTraitCollection.override.userInterfaceStyle == .dark { return .dark } else { diff --git a/Sources/FluentDarkModeKit/Extensions/UITextView+DarkModeKit.swift b/Sources/FluentDarkModeKit/Extensions/UITextView+DarkModeKit.swift index 94a774f..1481be1 100644 --- a/Sources/FluentDarkModeKit/Extensions/UITextView+DarkModeKit.swift +++ b/Sources/FluentDarkModeKit/Extensions/UITextView+DarkModeKit.swift @@ -14,7 +14,7 @@ extension UITextView { dm_updateDynamicColors() keyboardAppearance = { - if DMTraitCollection.current.userInterfaceStyle == .dark { + if DMTraitCollection.override.userInterfaceStyle == .dark { return .dark } else { diff --git a/Sources/FluentDarkModeKitExample/MainViewController.swift b/Sources/FluentDarkModeKitExample/MainViewController.swift index 7aab182..9a9b439 100644 --- a/Sources/FluentDarkModeKitExample/MainViewController.swift +++ b/Sources/FluentDarkModeKitExample/MainViewController.swift @@ -18,7 +18,8 @@ final class MainViewController: ViewController { Row(name: "UIActivityIndicatorView", vcType: UIActivityIndicatorViewVC.self), Row(name: "UIButton", vcType: UIButtonVC.self), Row(name: "UILabel", vcType: UILabelVC.self), - Row(name: "UIPageControl", vcType: UIPageControlVC.self) + Row(name: "UIPageControl", vcType: UIPageControlVC.self), + Row(name: "UIImageView", vcType: UIImageViewVC.self), ] lazy var tableView: UITableView = { diff --git a/Sources/FluentDarkModeKitExample/UIImageViewVC.swift b/Sources/FluentDarkModeKitExample/UIImageViewVC.swift new file mode 100644 index 0000000..b80e5d7 --- /dev/null +++ b/Sources/FluentDarkModeKitExample/UIImageViewVC.swift @@ -0,0 +1,39 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// + +import FluentDarkModeKit + +private extension UIColor { + var demoImage: UIImage { + let size = CGSize(width: 50, height: 50) + return UIGraphicsImageRenderer(size: size).image { context in + setFill() + context.fill(CGRect(origin: .zero, size: size)) + } + } +} + +final class UIImageViewVC: ViewController { + let imageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(.dm, light: UIColor.red.demoImage, dark: UIColor.green.demoImage) + return imageView + }() + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = UIColor(.dm, light: .white, dark: .black) + + view.addSubview(imageView) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + imageView.sizeToFit() + imageView.center = view.center + } +} diff --git a/Tests/FluentDarkModeKitUITests/DarkModeKitUITests.swift b/Tests/FluentDarkModeKitUITests/DarkModeKitUITests.swift index a39e7ba..4bd51a0 100644 --- a/Tests/FluentDarkModeKitUITests/DarkModeKitUITests.swift +++ b/Tests/FluentDarkModeKitUITests/DarkModeKitUITests.swift @@ -32,9 +32,21 @@ final class DarkModeKitUITests: XCTestCase { _test("UIPageControl") } + func testUILabel() { + _test("UILabel") + } + + func testUIImageView() { + _test("UIImageView") + } + func _test(_ className: String) { let app = XCUIApplication() - let refreshButton = app.navigationBars["FluentDarkModeKitExample.MainView"].buttons["Refresh"] + let navigationBarIdentifier = "0" // Current window index is used as navigation bar title + let refreshButtonIdentifier = "Refresh" + let compareNavigatonBarTitle = "FluentDarkModeKitExample.View" + + let refreshButton = app.navigationBars[navigationBarIdentifier].buttons[refreshButtonIdentifier] refreshButton.tap() // light mode refreshButton.tap() // dark mode @@ -45,14 +57,15 @@ final class DarkModeKitUITests: XCTestCase { let screenshot1 = app.screenshot() - app.navigationBars["FluentDarkModeKitExample.\(className)VC"].buttons["Back"].tap() + let backButtonTitle = navigationBarIdentifier + app.navigationBars[navigationBarIdentifier].buttons[backButtonTitle].tap() refreshButton.tap() // unspecified refreshButton.tap() // light mode uiviewStaticText.tap() let tabBarsQuery = app.tabBars tabBarsQuery.children(matching: .button).element(boundBy: 1).tap() - app.navigationBars["FluentDarkModeKitExample.View"].buttons["Refresh"].tap() + app.navigationBars[compareNavigatonBarTitle].buttons[refreshButtonIdentifier].tap() tabBarsQuery.children(matching: .button).element(boundBy: 0).tap() // dark mode let screenshot2 = app.screenshot()