Как я могу проверить, включен ли темный режим в iOS/iPadOS?

Начиная с iOS/iPadOS 13, доступен темный стиль пользовательского интерфейса, аналогичный темному режиму, представленному в macOS Mojave. Как я могу проверить, активировал ли пользователь общесистемный темный режим?

17 ответов

Решение

Вы должны проверить userInterfaceStyle переменная UITraitCollection Так же, как на tvOS и macOS.

switch traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}

Вы должны использовать traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) функция UIView / UIViewController обнаруживать изменения в интерфейсной среде (включая изменения в стиле пользовательского интерфейса).

Из документации разработчика Apple:

Система вызывает этот метод при изменении среды интерфейса iOS. Реализуйте этот метод в контроллерах представления и представлениях, в соответствии с потребностями вашего приложения, чтобы реагировать на такие изменения. Например, вы можете настроить макет подпредставлений контроллера представления, когда iPhone поворачивается из книжной в альбомную ориентацию. Реализация по умолчанию этого метода пуста.

Элементы пользовательского интерфейса системы по умолчанию (например, UITabBar или же UISearchBar) автоматически адаптируется к новому стилю пользовательского интерфейса.

Для iOS 13 вы можете использовать это свойство, чтобы проверить, является ли текущий стиль темным режимом или нет:

if #available(iOS 13.0, *) {
    if UITraitCollection.current.userInterfaceStyle == .dark {
        print("Dark mode")
    }
    else {
        print("Light mode")
    }
}

Как упоминал daveextreme, проверка стиля пользовательского интерфейса текущего представления не всегда возвращает системный стиль, когда вы используете overrideUserInterfaceStyleсвойство. В таких случаях может быть лучше использовать следующий код:

switch UIScreen.main.traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}

В objective-c вы хотите сделать:

if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){

        //is dark
}else{

    //is light

}

SwiftUI

С \.colorScheme ключ Environment переменная:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text(colorScheme == .dark ? "In dark mode" : "In light mode")
    }
}

Кроме того, он автоматически обновляется при изменении цветовой схемы среды.


UIKit

Для проверки тока все объекты соответствуют UITraitEnvironment протокол, включая все UIView подклассы и все UIViewConttroller подклассы имеют доступ к текущему стилю:

myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark

Чтобы обнаружить живые изменения стиля, вот полный подробный ответ

Для Swift:

if #available(iOS 12.0, *) {
  switch UIScreen.main.traitCollection.userInterfaceStyle {
    case .dark: // put your dark mode code here
    case .light: 
    case .unspecified: 
  }
}

Для цели C:

if (@available(iOS 12.0, *)) {
        switch (UIScreen.mainScreen.traitCollection.userInterfaceStyle) {
            case UIUserInterfaceStyleDark:
                // put your dark mode code here
                break;
            case UIUserInterfaceStyleLight:
            case UIUserInterfaceStyleUnspecified:
                break;
            default:
                break;
        }
}

Для получения дополнительной информации посмотрите это видео о WWDC2019.

1/ для UIView / UIViewController:

self.traitCollection.userInterfaceStyle == .dark

2 / для статического или другого:

UITraitCollection.current.userInterfaceStyle == .dark

НО:

//Never use this! You will get wrong value in app extensions (ex. ToDay widget)
UIScreen.main.traitCollection.userInterfaceStyle == .dark //WRONG!

Создайте функцию класса для метода записи 1 раз и используйте везде, где хотите

func isDarkMode() -> Bool{
    if #available(iOS 12.0, *) {
        if UIScreen.main.traitCollection.userInterfaceStyle == .dark {
            return true
        } else {
            return false
        }
    } else {
       return false
    }
}  

Цель C

Чтобы определить, когда темный режим включен или отключен через Центр управления, используйте уведомление "appDidBecomeActive", которое будет активировано, когда вы вернетесь в свое приложение.

//----------------------------------------------------------------------------
//                          viewWillAppear
//----------------------------------------------------------------------------
- (void)viewWillAppear {
    [super viewWillAppear];

    [[NSNotificationCenter defaultCenter]addObserver:self
                                   selector:@selector(appDidBecomeActive:)
                                   name:UIApplicationDidBecomeActiveNotification
                                   object:nil];

}

Не забудьте удалить его, когда закончите:

//------------------------------------------------------------------------------------
//                    viewWillDisappear
//------------------------------------------------------------------------------------
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [[NSNotificationCenter defaultCenter] removeObserver:self        
                                 name:UIApplicationDidBecomeActiveNotification 
                                 object:nil];

}

Делайте все, что вам нужно, когда меняется темный режим:

//----------------------------------------------------------------------------
//                          appDidBecomeActive
//----------------------------------------------------------------------------
-(void)appDidBecomeActive:(NSNotification*)note {
    if (@available(iOS 13.0, *)) {
        if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){
            //dark mode
        }
        else {
            //not dark mode
        }
    }
    else {
        //fall back for older versions
    }
}

Нижеприведенный вспомогательный метод, который работает с любой версией iOS:

var isDarkMode: Bool {
    guard #available(iOS 12.0, *) else {
        return false
    }

    return UIScreen.main.traitCollection.userInterfaceStyle == .dark
}

Применение:

view.backgroundColor = isDarkMode ? .black : .white

Лучшая точка для обнаружения изменений - это функция traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) UIView/UIViewController.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    let userInterfaceStyle = traitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark
    // Update your user interface based on the appearance
}

Обнаружение изменений внешнего вида является тривиальным путем переопределения traitCollectionDidChange в контроллерах представления. Затем просто получите доступ к traitCollection.userInterfaceStyle контроллера представления.

Однако важно помнить, что traitCollectionDidChange может вызываться для других изменений свойств, таких как вращение устройства. Вы можете проверить, отличается ли текущий вид, используя этот новый метод:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    let hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection) // Bool
    // Update your user interface based on the appearance
}
var isDarkMode: Bool {
    guard #available(iOS 12.0, *) else {
        return false
    }
    let window = (UIApplication.shared.delegate as? AppDelegate)?.window
    return window?.traitCollection.userInterfaceStyle == .dark
}

если вы не используете окно в AppDelegate, вызовите окно из SceneDelegate

Это похоже на большинство ответов выше, но это работает лучше, когда мы меняем режимы, используя

window?.overrideUserInterfaceStyle = .dark

можно назвать

isDarkMode ? .black : .white

Вы можете легко определить темный или светлый режим с помощью этого метода Swift 5.

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if traitCollection.userInterfaceStyle == .light {
    print("Light mode")
} else {
    print("Dark mode")
}}

Вы можете использовать это расширение:

import UIKit

extension UIApplication {
    @available(iOS 13.0, *)
    var userInterfaceStyle: UIUserInterfaceStyle? {
        return self.keyWindow?.traitCollection.userInterfaceStyle
    }
}

@available(iOS 13.0, *)
    func setSystemTheme() {
        switch UIApplication.shared.userInterfaceStyle {
        case .dark?:
            currentTheme = .dark
        case .light?:
            currentTheme = .light
        default:
            break
        }
    }

SwiftUI позволяет очень просто определить, включен ли темный режим. Нам просто нужно добавить переменную @Enviroment и использовать свойство .colorScheme для сканирования настроек на нашем устройстве и проверки того, включен ли темный режим.

Давайте посмотрим на код ниже.

      struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        ZStack {
            Color(colorScheme == .light ? .blue : .red)
            Text("Hello, World!")
        }
    }
}

В приведенном выше коде мы создаем переменную @Environment, чтобы увидеть, находится ли наше устройство в темном режиме. Затем внутри нашего вида тела мы устанавливаем цвет фона на красный, если он в темном режиме, или на синий, если он не в темном режиме, используя нашу переменную colorScheme внутри тернарного оператора.

Отличный вариант использования для этого — если вы хотите поддерживать различные пользовательские интерфейсы, когда устройство пользователя находится в темном режиме.

Удачного кодирования;

Вы можете использовать следующий код для проверки светлого или темного режима в вашем проекте:

       func viewDidLoad() {
    super.viewDidLoad()

    switch traitCollection.userInterfaceStyle {
        case .light, .unspecified:
            // light mode detected
        case .dark:
            // dark mode detected
    }
}

Вы также можете проверить изменения в стиле интерфейса:

       override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    let userInterfaceStyle = traitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark
    // Update your user interface based on the appearance
}

Как и в macOS, начиная с Mojave, вы можете определять изображения как для светлого, так и для темного режима в своем каталоге ресурсов, чтобы эти изображения использовались автоматически:

Может быть, какое-нибудь хорошее расширение?

public extension UIViewController {
    @available(iOS 12.0, *)
    public var isDarkMode: Bool { traitCollection.userInterfaceStyle == .dark }
}
Другие вопросы по тегам