• IOS13 for Dark Mode
  • It was, like, maybe a year ago,Mac OSThe system released a dark mode appearance, looking very exciting, when the daily use is also quite cool
  • Finally, withiPhone11When the new phone comes out,iOS 13The system has also been officially released, with the mobile version of dark mode also appearing in the public eye
  • Those of us whoiOSThe program ape also has things to do, the original project adaptationiOS13System, adaptationDark ModeDark mode
  • Although there is no requirement for forced adaptationDark Mode, butDarKBut adaptation is also imminent

Apps on iOS 13 are expected to support dark mode Use system colors and materials Create your own dynamic colors and images Leverage flexible infrastructure

Get the current mode

You can set the current appearance mode of the mobile phone in two ways

  • Settings –> Display and Brightness
  • Control center, long press the brightness adjustment button

Get the current mode

We need to select the current mode for which to adapt according to the different modes, iOS 13 added the API to get the current mode

Swift

// Get the current mode
let currentMode = UITraitCollection.current.userInterfaceStyle
if (currentMode == .dark) {
    print("Dark mode")}else if (currentMode == .light) {
    print("Light color mode")}else {
    print("Unknown mode")
}

open var userInterfaceStyle: UIUserInterfaceStyle { get } 

// All modes
public enum UIUserInterfaceStyle : Int {
    // Unspecified
    case unspecified
    // Light color mode
    case light
    // Dark mode
    case dark
}
Copy the code

OC language

if (@available(iOS 13.0, *)) {
    UIUserInterfaceStyle mode = UITraitCollection.currentTraitCollection.userInterfaceStyle;
    if (mode == UIUserInterfaceStyleDark) {
        NSLog(@" Dark mode");
    } else if (mode == UIUserInterfaceStyleLight) {
        NSLog(@" Light color mode");
    } else {
        NSLog(@" Unknown mode"); }}// Various enumerated values
typedef NS_ENUM(NSInteger.UIUserInterfaceStyle) {
    UIUserInterfaceStyleUnspecified.UIUserInterfaceStyleLight.UIUserInterfaceStyleDark,
} API_AVAILABLE(tvos(10.0)) API_AVAILABLE(ios(12.0)) API_UNAVAILABLE(watchos);
Copy the code

Listen for system mode changes

In iOS13, UIViewController follows two protocols: UITraitEnvironment and UIContentContainer

In the UITraitEnvironment protocol, we are provided with a way to listen for changes in the current schema

@protocol UITraitEnvironment <NSObject>
// Current mode
@property (nonatomic.readonly) UITraitCollection *traitCollection API_AVAILABLE(ios(8.0));

// Override this method to listen for schema changes
- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection API_AVAILABLE(ios(8.0));
@end
Copy the code
public protocol UITraitEnvironment : NSObjectProtocol {
    // Current mode
    @available(iOS 8.0*),var traitCollection: UITraitCollection { get }

    // Override this method to listen for schema changes
    @available(iOS 8.0*),func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
}


// How to use it
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    // This is executed every time the mode changes
    print("The pattern has changed.")}Copy the code

Color dependent adaptation

  • The adaptation of different modes mainly involves the adaptation of colors and pictures
  • Color adaptation, including the relevant background color and font color
  • When the system mode is switched, we do not need to operate, the system will automatically render the page, just need to do different modes of color and pictures

UIColor

  • iOS13beforeUIColorCan only represent one color fromiOS13startUIColorIs a dynamic color that can represent different colors in different modes
  • The following isiOS13Dynamic color types provided by the system. Use the following color values. No special treatment is required during mode switching
@interface UIColor (UIColorSystemColors)
#pragma mark System colors

@property (class.nonatomic.readonly) UIColor *systemRedColor          API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemGreenColor        API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemBlueColor         API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemOrangeColor       API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemYellowColor       API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemPinkColor         API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemPurpleColor       API_AVAILABLE(ios(9.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemTealColor         API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemIndigoColor       API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
In Light mode, systemGray6Color tends to be white
@property (class.nonatomic.readonly) UIColor *systemGrayColor         API_AVAILABLE(ios(7.0), tvos(9.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *systemGray2Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *systemGray3Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *systemGray4Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *systemGray5Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *systemGray6Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);

#pragma mark Foreground colors
@property (class.nonatomic.readonly) UIColor *labelColor              API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *secondaryLabelColor     API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *tertiaryLabelColor      API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *quaternaryLabelColor    API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
// The foreground of the system link
@property (class.nonatomic.readonly) UIColor *linkColor               API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
// Placeholder text color
@property (class.nonatomic.readonly) UIColor *placeholderTextColor    API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
// The color of the border or divider
@property (class.nonatomic.readonly) UIColor *separatorColor          API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class.nonatomic.readonly) UIColor *opaqueSeparatorColor    API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);

#pragma mark Background colors
@property (class.nonatomic.readonly) UIColor *systemBackgroundColor                   API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *secondarySystemBackgroundColor          API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *tertiarySystemBackgroundColor           API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *systemGroupedBackgroundColor            API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *secondarySystemGroupedBackgroundColor   API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *tertiarySystemGroupedBackgroundColor    API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);

#pragma mark Fill colors
@property (class.nonatomic.readonly) UIColor *systemFillColor                         API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *secondarySystemFillColor                API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *tertiarySystemFillColor                 API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class.nonatomic.readonly) UIColor *quaternarySystemFillColor               API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);

#pragma mark Other colors
// These two are non-dynamic color values
@property(class.nonatomic.readonly) UIColor *lightTextColor API_UNAVAILABLE(tvos);    // for a dark background
@property(class.nonatomic.readonly) UIColor *darkTextColor API_UNAVAILABLE(tvos);     // for a light background

@property(class.nonatomic.readonly) UIColor *groupTableViewBackgroundColor API_DEPRECATED_WITH_REPLACEMENT("systemGroupedBackgroundColor", ios(2.0.13.0), tvos(13.0.13.0));
@property(class.nonatomic.readonly) UIColor *viewFlipsideBackgroundColor API_DEPRECATED("", ios(2.0.7.0)) API_UNAVAILABLE(tvos);
@property(class.nonatomic.readonly) UIColor *scrollViewTexturedBackgroundColor API_DEPRECATED("", ios(3.2.7.0)) API_UNAVAILABLE(tvos);
@property(class.nonatomic.readonly) UIColor *underPageBackgroundColor API_DEPRECATED("", ios(5.0.7.0)) API_UNAVAILABLE(tvos);

@end
Copy the code
  • The color types provided by the above system cannot meet our normal development needs, and most of the color values are customized
  • The system also provides a way to create custom colors
@available(iOS 13.0*),public init(dynamicProvider: @escaping (UITraitCollection) - >UIColor)
Copy the code

In the OC

+ (UIColor *)colorWithDynamicProvider:(UIColor* (^) (UITraitCollection *traitCollection))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
- (UIColor *)initWithDynamicProvider:(UIColor* (^) (UITraitCollection *traitCollection))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
Copy the code
  • The above method accepts a closure (block)
  • When the system inLightModeandDarkModeThis callback is automatically triggered when switching between
  • The callback returns oneUITraitCollection, which mode can be determined according to the object
fileprivate func getColor(a) -> UIColor {
    return UIColor { (collection) -> UIColor in
        if (collection.userInterfaceStyle == .dark) {
            return UIColor.red
        }
        return UIColor.green
    }
}
Copy the code

In addition to the above two methods, UIColor also adds an instance method

// Get the corresponding UIColor from the current traitCollection
@available(iOS 13.0, *)
open func resolvedColor(with traitCollection: UITraitCollection) -> UIColor
Copy the code

CGColor

  • UIColorJust set the background color and text color class, can be set dynamically
  • But what if you need to set attributes like border color
  • To set the border properties above, use theCGColorClass, but iniOS13In theCGColorIt is not a dynamic color value and can only represent one color
  • In the method that listens for mode changestraitCollectionDidChangeAccording to different modes
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    // This is executed every time the mode changes
    if(previousTraitCollection? .userInterfaceStyle == .dark) { redView.layer.borderColor =UIColor.red.cgColor
    } else {
        redView.layer.borderColor = UIColor.green.cgColor
    }
}
Copy the code

Graphics adapter

  • iniOSIn, the pictures are basically placed inAssets.xcassetsInside, so the picture of the adaptation, we are relatively troublesome
  • Under normal circumstances, this is the way to deal with

  • If you need to fit different modes, you need two different sets of images and do the following Settings
  • In setting upAppearancesWhen, we chooseAny, DarkIt’s fine (just for dark and non-dark mode)

Adaptation related

Current page mode

  • If there is no adaptation in the original projectDark Mode, when you switch toDark ModeAfter that, you may find that the color of some parts of the page automatically matches
  • Components that have not been set to a background color or text color, inDark ModeIn mode, it’s black
  • Here we need the true pair to be aloneAppForce set toLight Modemodel
// Setting the properties will only affect the current view, not the previous controller or the present controller
@available(iOS 13.0, *)
open var overrideUserInterfaceStyle: UIUserInterfaceStyle

// An example
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    // This is executed every time the mode changes
    if(previousTraitCollection? .userInterfaceStyle == .dark) {// In Dark mode, force change to Light mode
        overrideUserInterfaceStyle = .light
    }
}
Copy the code

Enforces the display mode of the project

  • This method can only be modified for a single page and disabled for the entire project if necessaryDarkmodel
  • You can modify itwindowtheoverrideUserInterfaceStyleattribute
  • inXcode11In the project you created,windowfromAppDelegateMove to theSceneDelegateAdd the following code to change the display mode globally
let scene = UIApplication.shared.connectedScenes.first? .delegateas? SceneDelegatescene? .window? .overrideUserInterfaceStyle = .lightCopy the code

In the previous project, you could set the following code in the AppDelegate

window.overrideUserInterfaceStyle = .light
Copy the code

For my simple project, the above code does force the current mode to be changed, but the status bar display will not be changed. Is there something missing

The ultimate solution

  • Need to be ininfo.plistAdd to fileUser Interface StyleConfigure and set toLight
<key>UIUserInterfaceStyle</key>
<string>Light</string>
Copy the code

In React Native, the status bar still displays different colors according to different modes.

Update the Status Bar

Apple also made some changes to the Status Bar in iOS13, prior to iOS13

public enum UIStatusBarStyle : Int {
    case `default` // The default text is black

    @available(iOS 7.0*),case lightContent // Text is white
}
Copy the code

From iOS13 onwards there are three states of UIStatusBarStyle

public enum UIStatusBarStyle : Int {
    case `default` // Automatically select black or white

    @available(iOS 7.0*),case lightContent // Text is white
    
    @available(iOS 13.0*),case darkContent // Text black
}
Copy the code

In the React Native code, set the color of the status bar to black

<StatusBar barStyle={'dark-content'} / >Copy the code
  • The code above is iniOS13The system is invalid in the phone
  • Although this is set up in the code abovedark-contentPattern, but iniOSIn native codedark-contentThe actual isUIStatusBarStyleDefault
  • In the fileRCTStatusBarManager.mIn the
RCT_ENUM_CONVERTER(UIStatusBarStyle, (@ {@"default": @ (UIStatusBarStyleDefault),
  @"light-content": @ (UIStatusBarStyleLightContent),
  @"dark-content": @ (UIStatusBarStyleDefault),}),UIStatusBarStyleDefault, integerValue);
Copy the code

Modify the above code

@"dark-content": @(@available(iOS 13.0, *)?UIStatusBarStyleDarkContent : UIStatusBarStyleDefault),
Copy the code

IOS13 other updates

Apple login

Sign In with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year.

  • ifAPPSupport three-party login (Facbook,Google, WeChat,QQ, Alipay, etc.), must support Apple landing, and to the front
  • As for theAppleThe style of the login button is recommendedAppleThe button styles provided have been adapted to various devices for your referenceSign In with Apple

LaunchImage

LaunchImage, soon to be scrapped

  • fromiOS 8Apple was introducedLaunchScreen, we can setLaunchScreenTo be the launch page.
  • You can still use it nowLaunchImageBut as Apple devices get bigger and bigger, it’s a bit trickier to fit
  • useLaunchScreenIt would have been easier,LaunchScreenIs to supportAutoLayoutandSizeClassSo it’s easy to adapt to all kinds of screens.
  • ⚠️ from April 2020, allAppWill have to provideLaunchScreenAnd theLaunchImageIs about to retire from history

UIWebView

'UIWebView' was deprecated in iOS 12.0: No longer supported; please adopt WKWebView.

As of iOS 13, UIWebView is no longer supported. Replace it with WKWebView asap

@available(iOS, introduced: 2.0, deprecated: 12.0, message: "No longer supported; please adopt WKWebView.")
open class UIWebView : UIView.NSCoding.UIScrollViewDelegate {}Copy the code

Please scan the following wechat official account and subscribe to my blog!