Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Allow not to use UIImageAsset on iOS 13 #88

Merged
merged 3 commits into from
Jul 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions FluentDarkModeKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,14 @@
8CDA62A52366DAA9004895B5 /* DMDynamicColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CDA628B2366DAA9004895B5 /* DMDynamicColor.h */; settings = {ATTRIBUTES = (Public, ); }; };
8CE066CF239E5582002CE16D /* UIColor+DarkModeKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CC8D86C2398E4EC0043276A /* UIColor+DarkModeKit.m */; };
8CE066D0239E5586002CE16D /* UIImage+DarkModeKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CC8D8722398E7A30043276A /* UIImage+DarkModeKit.m */; };
EA1BAF6724C581C5006E755F /* UIView+DarkModeKitSwizzling.h in Headers */ = {isa = PBXBuildFile; fileRef = EA1BAF6524C581C5006E755F /* UIView+DarkModeKitSwizzling.h */; };
EA1BAF6824C581C5006E755F /* UIView+DarkModeKitSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = EA1BAF6624C581C5006E755F /* UIView+DarkModeKitSwizzling.m */; };
EA1BAF6F24C58447006E755F /* UIImage+DarkModeKitSwizzling.h in Headers */ = {isa = PBXBuildFile; fileRef = EA1BAF6D24C58447006E755F /* UIImage+DarkModeKitSwizzling.h */; };
EA1BAF7024C58447006E755F /* UIImage+DarkModeKitSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = EA1BAF6E24C58447006E755F /* UIImage+DarkModeKitSwizzling.m */; };
EA2EA50024A1CBF2001AE312 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA2EA4FE24A1CAD5001AE312 /* SceneDelegate.swift */; };
EA7316F1248F5055009AE037 /* UILabelVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7316EF248F5050009AE037 /* UILabelVC.swift */; };
EAC41E2F24CADD6E0033C9AC /* DMEnvironmentConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = EAC41E2D24CADD6E0033C9AC /* DMEnvironmentConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
EAC41E3024CADD6E0033C9AC /* DMEnvironmentConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = EAC41E2E24CADD6E0033C9AC /* DMEnvironmentConfiguration.m */; };
EAE6065624A9DA1B001304D1 /* UIImageViewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAE6065324A9D9E0001304D1 /* UIImageViewVC.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -148,8 +154,14 @@
8CDA62892366DAA9004895B5 /* DMDynamicImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DMDynamicImage.m; sourceTree = "<group>"; };
8CDA628A2366DAA9004895B5 /* DarkModeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarkModeManager.swift; sourceTree = "<group>"; };
8CDA628B2366DAA9004895B5 /* DMDynamicColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DMDynamicColor.h; sourceTree = "<group>"; };
EA1BAF6524C581C5006E755F /* UIView+DarkModeKitSwizzling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+DarkModeKitSwizzling.h"; sourceTree = "<group>"; };
EA1BAF6624C581C5006E755F /* UIView+DarkModeKitSwizzling.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+DarkModeKitSwizzling.m"; sourceTree = "<group>"; };
EA1BAF6D24C58447006E755F /* UIImage+DarkModeKitSwizzling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+DarkModeKitSwizzling.h"; sourceTree = "<group>"; };
EA1BAF6E24C58447006E755F /* UIImage+DarkModeKitSwizzling.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImage+DarkModeKitSwizzling.m"; 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>"; };
EAC41E2D24CADD6E0033C9AC /* DMEnvironmentConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DMEnvironmentConfiguration.h; sourceTree = "<group>"; };
EAC41E2E24CADD6E0033C9AC /* DMEnvironmentConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DMEnvironmentConfiguration.m; sourceTree = "<group>"; };
EAE6065324A9D9E0001304D1 /* UIImageViewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageViewVC.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -214,15 +226,21 @@
8CDA62732366DAA9004895B5 /* DMDynamicColor.m */,
8CDA62762366DAA9004895B5 /* DMDynamicImage.h */,
8CDA62892366DAA9004895B5 /* DMDynamicImage.m */,
EAC41E2D24CADD6E0033C9AC /* DMEnvironmentConfiguration.h */,
EAC41E2E24CADD6E0033C9AC /* DMEnvironmentConfiguration.m */,
8CDA62712366DAA9004895B5 /* DMTraitCollection.h */,
8CDA62722366DAA9004895B5 /* DMTraitCollection.m */,
8CC8D86F2398E7520043276A /* DMNamespace.h */,
8CC8D86B2398E4EC0043276A /* UIColor+DarkModeKit.h */,
8CC8D86C2398E4EC0043276A /* UIColor+DarkModeKit.m */,
8CC8D8712398E7A30043276A /* UIImage+DarkModeKit.h */,
8CC8D8722398E7A30043276A /* UIImage+DarkModeKit.m */,
EA1BAF6D24C58447006E755F /* UIImage+DarkModeKitSwizzling.h */,
EA1BAF6E24C58447006E755F /* UIImage+DarkModeKitSwizzling.m */,
8CB63E3F238551F3008ABCE2 /* UIView+DarkModeKit.h */,
8CB63E40238551F3008ABCE2 /* UIView+DarkModeKit.m */,
EA1BAF6524C581C5006E755F /* UIView+DarkModeKitSwizzling.h */,
EA1BAF6624C581C5006E755F /* UIView+DarkModeKitSwizzling.m */,
);
path = DarkModeCore;
sourceTree = "<group>";
Expand Down Expand Up @@ -337,7 +355,10 @@
buildActionMask = 2147483647;
files = (
8CC8D86D2398E4EC0043276A /* UIColor+DarkModeKit.h in Headers */,
EA1BAF6724C581C5006E755F /* UIView+DarkModeKitSwizzling.h in Headers */,
EA1BAF6F24C58447006E755F /* UIImage+DarkModeKitSwizzling.h in Headers */,
8CC8D8702398E7520043276A /* DMNamespace.h in Headers */,
EAC41E2F24CADD6E0033C9AC /* DMEnvironmentConfiguration.h in Headers */,
8CDA628D2366DAA9004895B5 /* DMTraitCollection.h in Headers */,
8CDA628C2366DAA9004895B5 /* FluentDarkModeKit.h in Headers */,
8CB63E41238551F3008ABCE2 /* UIView+DarkModeKit.h in Headers */,
Expand Down Expand Up @@ -531,9 +552,11 @@
buildActionMask = 2147483647;
files = (
8CDA62972366DAA9004895B5 /* UIScrollView+DarkModeKit.swift in Sources */,
EAC41E3024CADD6E0033C9AC /* DMEnvironmentConfiguration.m in Sources */,
8CB63E42238551F3008ABCE2 /* UIView+DarkModeKit.m in Sources */,
8CDA62A12366DAA9004895B5 /* UITextField+DarkModeKit.swift in Sources */,
8CDA62952366DAA9004895B5 /* UIWindow+DarkModeKit.swift in Sources */,
EA1BAF6824C581C5006E755F /* UIView+DarkModeKitSwizzling.m in Sources */,
8CDA629E2366DAA9004895B5 /* UIViewController+DarkModeKit.swift in Sources */,
8CDA62992366DAA9004895B5 /* UIImageView+DarkModeKit.swift in Sources */,
8CDA62962366DAA9004895B5 /* UIProgressView+DarkModeKit.swift in Sources */,
Expand All @@ -551,6 +574,7 @@
8CDA62922366DAA9004895B5 /* UIToolbar+DarkModeKit.swift in Sources */,
8CDA629A2366DAA9004895B5 /* UIPageControl+DarkModeKit.swift in Sources */,
8CDA62932366DAA9004895B5 /* UIButton+DarkModeKit.swift in Sources */,
EA1BAF7024C58447006E755F /* UIImage+DarkModeKitSwizzling.m in Sources */,
8CDA629B2366DAA9004895B5 /* UITableView+DarkModeKit.swift in Sources */,
8CDA629F2366DAA9004895B5 /* UILabel+DarkModeKit.swift in Sources */,
);
Expand Down
10 changes: 8 additions & 2 deletions Sources/DarkModeCore/DMDynamicImage.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ - (instancetype)initWithLightImage:(UIImage *)lightImage darkImage:(UIImage *)da
- (UIImage *)resolvedImage {
if (DMTraitCollection.overrideTraitCollection.userInterfaceStyle == DMUserInterfaceStyleDark) {
return self.darkImage;
} else {
return self.lightImage;
}
return self.lightImage;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
Expand Down Expand Up @@ -88,6 +87,13 @@ - (UIImage *)imageWithHorizontallyFlippedOrientation {
darkImage:[self.darkImage imageWithHorizontallyFlippedOrientation]];
}

- (UIImage *)imageWithConfiguration:(UIImageConfiguration *)configuration API_AVAILABLE(ios(13.0)) {
if (configuration.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
return [_darkImage imageWithConfiguration:configuration];
}
return [_lightImage imageWithConfiguration:configuration];
}

- (id)copy {
return [self copyWithZone:nil];
}
Expand Down
18 changes: 18 additions & 0 deletions Sources/DarkModeCore/DMEnvironmentConfiguration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface DMEnvironmentConfiguration : NSObject

@property (nonatomic) BOOL useImageAsset; // Defaults to NO

- (instancetype)init;

@end

NS_ASSUME_NONNULL_END
18 changes: 18 additions & 0 deletions Sources/DarkModeCore/DMEnvironmentConfiguration.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//

#import "DMEnvironmentConfiguration.h"

@implementation DMEnvironmentConfiguration

- (instancetype)init {
self = [super init];
if (self) {
_useImageAsset = NO;
}
return self;
}

@end
8 changes: 4 additions & 4 deletions Sources/DarkModeCore/DMTraitCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#import <UIKit/UIKit.h>

@class UITraitCollection;
@class UITraitCollection, DMEnvironmentConfiguration;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -35,9 +35,9 @@ typedef NS_ENUM(NSInteger, DMUserInterfaceStyle) {
+ (void)registerWithViewController:(UIViewController *)viewController syncImmediately:(BOOL)syncImmediately animated:(BOOL)animated;
+ (void)unregister;

// MARK: - Swizzling
// TODO: move swizzling to private header
+ (void)swizzleUIScreenTraitCollectionDidChange API_AVAILABLE(ios(13.0));
// MARK: - Setup
// TODO: Move to private header
+ (void)setupEnvironmentWithConfiguration:(DMEnvironmentConfiguration *)configuration;

@end

Expand Down
24 changes: 22 additions & 2 deletions Sources/DarkModeCore/DMTraitCollection.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
// Licensed under the MIT License.
//

#import "DMEnvironmentConfiguration.h"
#import "DMTraitCollection.h"
#import "UIView+DarkModeKit.h"
#import "UIView+DarkModeKitSwizzling.h"
#import "UIImage+DarkModeKitSwizzling.h"

@import ObjectiveC;

Expand Down Expand Up @@ -243,7 +245,7 @@ + (void)unregister {
}

// MARK: - Swizzling
+ (void)swizzleUIScreenTraitCollectionDidChange {
+ (void)swizzleUIScreenTraitCollectionDidChange API_AVAILABLE(ios(13.0)) {
static dispatch_once_t onceToken;
__weak typeof(self) weakSelf = self;
dispatch_once(&onceToken, ^{
Expand All @@ -258,6 +260,24 @@ + (void)swizzleUIScreenTraitCollectionDidChange {
});
}

+ (void)setupEnvironmentWithConfiguration:(DMEnvironmentConfiguration *)configuration {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (@available(iOS 13.0, *)) {
[DMTraitCollection swizzleUIScreenTraitCollectionDidChange];
[UIView swizzleTraitCollectionDidChangeToDMTraitCollectionDidChange];
[UIViewController swizzleTraitCollectionDidChangeToDMTraitCollectionDidChange];
if (!configuration.useImageAsset)
[UIImage dm_swizzleIsEqual];
}
else {
[UIView dm_swizzleSetTintColor];
[UIView dm_swizzleSetBackgroundColor];
[UIImage dm_swizzleIsEqual];
}
});
}

@end

@interface UIScreen (DMTraitEnvironment) <DMTraitEnvironment>
Expand Down
1 change: 1 addition & 0 deletions Sources/DarkModeCore/FluentDarkModeKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#import <FluentDarkModeKit/DMDynamicColor.h>
#import <FluentDarkModeKit/DMDynamicImage.h>
#import <FluentDarkModeKit/DMEnvironmentConfiguration.h>
#import <FluentDarkModeKit/DMTraitCollection.h>
#import <FluentDarkModeKit/UIColor+DarkModeKit.h>
#import <FluentDarkModeKit/UIImage+DarkModeKit.h>
Expand Down
2 changes: 0 additions & 2 deletions Sources/DarkModeCore/UIImage+DarkModeKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ NS_ASSUME_NONNULL_BEGIN

@interface UIImage (DarkModeKit)

+ (void)dm_swizzleIsEqual;

+ (UIImage *)dm_imageWithLightImage:(UIImage *)lightImage darkImage:(UIImage *)darkImage
NS_SWIFT_UNAVAILABLE("Use init(_:light:dark:) instead.");

Expand Down
54 changes: 16 additions & 38 deletions Sources/DarkModeCore/UIImage+DarkModeKit.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,31 @@
//

#import "UIImage+DarkModeKit.h"
#import "UIImage+DarkModeKitSwizzling.h"
#import "DMDynamicImage.h"
#import "DMTraitCollection.h"

@import ObjectiveC;

@implementation UIImage (DarkModeKit)

+ (void)dm_swizzleIsEqual {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL selector = @selector(isEqual:);
Method method = class_getInstanceMethod(self, selector);
if (!method)
NSAssert(NO, @"Method not found for [UIImage isEqual:]");

IMP imp = method_getImplementation(method);
class_replaceMethod(self, selector, imp_implementationWithBlock(^BOOL(UIImage *self, UIImage *other) {
/// On iOS 13, UIImage `isEqual:` somehow changes internally and doesn't work for `NSProxy`,
/// here we forward the message to internal images manually
UIImage *realSelf = self;
UIImage *realOther = other;
if (object_getClass(self) == DMDynamicImageProxy.class) {
realSelf = ((DMDynamicImageProxy *)self).resolvedImage;
}
if (object_getClass(other) == DMDynamicImageProxy.class) {
realOther = ((DMDynamicImageProxy *)other).resolvedImage;
}
return ((BOOL(*)(UIImage *, SEL, UIImage *))imp)(realSelf, selector, realOther);
}), method_getTypeEncoding(method));
});
}

+ (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];
if ([UIImage useUIImageAsset]) {
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];
Expand Down
18 changes: 18 additions & 0 deletions Sources/DarkModeCore/UIImage+DarkModeKitSwizzling.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (DarkModeKitSwizzling)

@property (class, readonly) BOOL useUIImageAsset;

+ (void)dm_swizzleIsEqual;

@end

NS_ASSUME_NONNULL_END
46 changes: 46 additions & 0 deletions Sources/DarkModeCore/UIImage+DarkModeKitSwizzling.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//

#import "UIImage+DarkModeKitSwizzling.h"
#import "DMDynamicImage.h"

@import ObjectiveC;

static BOOL _useUIImageAsset = YES;

@implementation UIImage (DarkModeKitSwizzling)

+ (BOOL)useUIImageAsset {
return _useUIImageAsset;
}

+ (void)dm_swizzleIsEqual {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL selector = @selector(isEqual:);
Method method = class_getInstanceMethod(self, selector);
if (!method)
NSAssert(NO, @"Method not found for [UIImage isEqual:]");

IMP imp = method_getImplementation(method);
class_replaceMethod(self, selector, imp_implementationWithBlock(^BOOL(UIImage *self, UIImage *other) {
/// On iOS 13, UIImage `isEqual:` somehow changes internally and doesn't work for `NSProxy`,
/// here we forward the message to internal images manually
UIImage *realSelf = self;
UIImage *realOther = other;
if (object_getClass(self) == DMDynamicImageProxy.class) {
realSelf = ((DMDynamicImageProxy *)self).resolvedImage;
}
if (object_getClass(other) == DMDynamicImageProxy.class) {
realOther = ((DMDynamicImageProxy *)other).resolvedImage;
}
return ((BOOL(*)(UIImage *, SEL, UIImage *))imp)(realSelf, selector, realOther);
}), method_getTypeEncoding(method));

_useUIImageAsset = NO;
});
}

@end
3 changes: 0 additions & 3 deletions Sources/DarkModeCore/UIView+DarkModeKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ NS_ASSUME_NONNULL_BEGIN

@interface UIView (DarkModeKit) <DMTraitEnvironment>

+ (void)dm_swizzleSetBackgroundColor;
+ (void)dm_swizzleSetTintColor;

- (void)dm_updateDynamicColors API_DEPRECATED("dm_updateDynamicColors is deprecated and will not be called on iOS 13.0, use dmTraitCollectionDidChange: instead", ios(11.0, 13.0));;
- (void)dm_updateDynamicImages API_DEPRECATED("dm_updateDynamicImages is deprecated and will not be called on iOS 13.0, use dmTraitCollectionDidChange: instead", ios(11.0, 13.0));;

Expand Down
Loading