macOS 앱의 다크 모드 지원

14138 단어 MacOSXSwiftDarkMode

소개



macOS에서는 10.14(2018년 릴리스)부터 어두운 모드가 추가되었습니다.

macOS 10.14부터 앱에서 고유한 색상을 사용하는 경우 라이트 모드와 어두운 모드의 색상을 준비해야 합니다. 라이트/다크용 컬러는 컬러 에셋을 이용하여 준비할 수 있습니다.



컬러 에셋에서 다음 코드로 외관 모드에 맞는 컬러 객체를 생성할 수 있습니다.
let color = NSColor(named: NSColor.Name("MyColor"))

하지만 이 방법은 모드를 전환할 때 시작 중인 앱에서 자동으로 색상을 변경하지 않습니다. macOS 10.15에서는 NSColor에 init(name:dynamicProvider:) 이니셜라이저가 추가되어 있어 문서에 설명은 없지만, 알아보기 위해 이것을 사용하면 동적으로 변경할 수 있다고 생각합니다. macOS 10.14에서는 어떻게합니까?

macOS 10.14에서 어두운 모드 지원



macOS 10.14에서는 사용자 정의 색상을 View로 설정한 경우 모드 변경을 감지하고 색상을 다시 설정하는 코드를 작성해야 합니다.

어두운 모드인지 결정



어두운 모드인지 결정 isDarkMode 컴퓨팅 속성을 NSApplication에 생성합니다.
extension NSApplication {
    public var isDarkMode: Bool {
        if #available(OSX 10.14, *) {
            let name = effectiveAppearance.name
            return name == .darkAqua
        }
        else {
            return false
        }
    }
}

외관 모드에 따라 컬러 객체를 반환합니다.



라이트/다크 모드용의 칼라 오브젝트를 돌려주는 적절한 메소드를 구현합니다.
struct CustomColors {
    static var background: NSColor {
        if NSApplication.shared.isDarkMode {
            return NSColor(red: 34.0 / 255.0, green: 34.0 / 255.0, blue: 34.0 / 255.0, alpha: 1.0)
        }
        return .white    // for Light Mode
    }
}

외관 모드 변경을 감지합니다.



모양 모드가 변경되면 NSView의 viewDidChangeEffectiveAppearance 메서드가 호출됩니다. 이 메소드를 오버라이드(override) 해, 칼라 오브젝트를 재설정하도록(듯이) 합니다.
class CustomView: NSView {

    @available(OSX 10.14, *)
    override func viewDidChangeEffectiveAppearance() {
        layer?.backgroundColor = CustomColors.background.cgColor
    }
}

이제 동적으로 색상을 변경할 수 있습니다. 단, 이 방법은 각 뷰에서 상속 클래스를 만들어야 하기 때문에 사용하기 편하지 않을 때가 있습니다.

그래서 저는 다음과 같은 클래스를 만들어 감시하도록 하고 있습니다.
class AppearanceMonitor: NSView {

    public static let appearanceChangedNotification = NSNotification.Name("AppearanceChangedNotification")
    public static let shared                        = AppearanceMonitor(frame: .zero)

    public var isMonitoring: Bool {
        superview != nil
    }

    override func viewDidMoveToSuperview() {
        guard let _ = superview else {
            print("[\(self.className)] Monitoring stopped.")
            return
        }
        print("[\(self.className)] Monitoring started.")
    }

    @available(OSX 10.14, *)
    override func viewDidChangeEffectiveAppearance() {
        NotificationCenter.default.post(name: AppearanceMonitor.appearanceChangedNotification, object: nil, userInfo: nil)
    }

    public func start(with viewController: NSViewController) {
        if !isMonitoring {
            viewController.view.addSubview(self)
        }
    }

    public func stop() {
        if isMonitoring {
            removeFromSuperview()
        }
    }
}
class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // 監視用のビューを貼る(frame=.zeroなので見た目には影響がない)
        AppearanceMonitor.shared.start(with: self)
    }

    override func viewWillAppear() {
        super.viewWillAppear()

        NotificationCenter.default.addObserver(self,
                                               selector: #selector(appearanceChanged),
                                               name: AppearanceMonitor.appearanceChangedNotification,
                                               object: nil)
    }

    override func viewWillDisappear() {
        super.viewWillDisappear()

        NotificationCenter.default.removeObserver(self,
                                                  name: AppearanceMonitor.appearanceChangedNotification,
                                                  object: nil)
    }

    @objc func appearanceChanged() {
        // ライト/ダーク・モード切り替え時に呼ばれるのでUIを更新する
    }
}

덧붙여 그 밖에 AppleInterfaceThemeChangedNotification 를 감시하는 방법도 있습니다만, 공식 문서에 기재가 없는 (?) 때문에, 적극적으로 사용해 좋은 것일까 괴롭습니다.

프로그래밍 방식으로 라이트/다크 모드 전환



마지막으로 프로그램에서 라이트/다크 모드를 전환하는 방법을 소개합니다.
// ダークモードにする
NSApp.appearance = NSAppearance(named: .darkAqua)
// ライドモードにする
NSApp.appearance = NSAppearance(named: .aqua)
// プログラムでの設定を解除する -> Macの設定に従う
NSApp.appearance = nil

참고



Supporting Dark Mode in Your Interface
htps : //로 ゔぇぺぺr. 아 ぇ. 코 m / 도쿠 멘 타치 온 / x 코 데 / 삿포 r 찐 g_ 다 rk_ 모로 _ 네 _ r_

좋은 웹페이지 즐겨찾기