Migrate UIImage APIs to using UIImageAsset on iOS13 (#82)

* Mark DMTraitCollection.current as deprecated

* System built-in support for dark/light mode UIImage
This commit is contained in:
Levin Li 2020-07-01 18:05:08 +08:00 коммит произвёл GitHub
Родитель 55e55946e1
Коммит 1f11a409e0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 89 добавлений и 15 удалений

Просмотреть файл

@ -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 = "<group>"; };
EA2EA4FE24A1CAD5001AE312 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
EA7316EF248F5050009AE037 /* UILabelVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UILabelVC.swift; sourceTree = "<group>"; };
EAE6065324A9D9E0001304D1 /* UIImageViewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageViewVC.swift; sourceTree = "<group>"; };
/* 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 */,

Просмотреть файл

@ -22,7 +22,7 @@
}
- (UIColor *)resolvedColor {
return [self resolvedColorWithTraitCollection:DMTraitCollection.currentTraitCollection];
return [self resolvedColorWithTraitCollection:DMTraitCollection.overrideTraitCollection];
}
- (UIColor *)resolvedColorWithTraitCollection:(DMTraitCollection *)traitCollection {

Просмотреть файл

@ -37,7 +37,7 @@
}
- (UIImage *)resolvedImage {
if (DMTraitCollection.currentTraitCollection.userInterfaceStyle == DMUserInterfaceStyleDark) {
if (DMTraitCollection.overrideTraitCollection.userInterfaceStyle == DMUserInterfaceStyleDark) {
return self.darkImage;
} else {
return self.lightImage;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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];
}

Просмотреть файл

@ -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];
}

Просмотреть файл

@ -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))

Просмотреть файл

@ -14,7 +14,7 @@ extension UIScrollView {
dm_updateDynamicColors()
indicatorStyle = {
if DMTraitCollection.current.userInterfaceStyle == .dark {
if DMTraitCollection.override.userInterfaceStyle == .dark {
return .white
}
else {

Просмотреть файл

@ -18,7 +18,7 @@ extension UITextField {
}
keyboardAppearance = {
if DMTraitCollection.current.userInterfaceStyle == .dark {
if DMTraitCollection.override.userInterfaceStyle == .dark {
return .dark
}
else {

Просмотреть файл

@ -14,7 +14,7 @@ extension UITextView {
dm_updateDynamicColors()
keyboardAppearance = {
if DMTraitCollection.current.userInterfaceStyle == .dark {
if DMTraitCollection.override.userInterfaceStyle == .dark {
return .dark
}
else {

Просмотреть файл

@ -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 = {

Просмотреть файл

@ -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
}
}

Просмотреть файл

@ -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()