123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- //
- // NSObject+Theme.swift
- // SwiftTheme
- //
- // Created by Gesen on 16/1/22.
- // Copyright © 2016年 Gesen. All rights reserved.
- //
- import UIKit
- fileprivate typealias setCGColorValueIMP = @convention(c) (NSObject, Selector, CGColor) -> Void
- fileprivate typealias setCGFloatValueIMP = @convention(c) (NSObject, Selector, CGFloat) -> Void
- fileprivate typealias setValueForStateIMP = @convention(c) (NSObject, Selector, AnyObject, UIControl.State) -> Void
- fileprivate typealias setKeyboardValueIMP = @convention(c) (NSObject, Selector, UIKeyboardAppearance) -> Void
- fileprivate typealias setActivityStyleValueIMP = @convention(c) (NSObject, Selector, UIActivityIndicatorView.Style) -> Void
- fileprivate typealias setScrollStyleValueIMP = @convention(c) (NSObject, Selector, UIScrollView.IndicatorStyle) -> Void
- #if os(iOS)
- fileprivate typealias setBarStyleValueIMP = @convention(c) (NSObject, Selector, UIBarStyle) -> Void
- fileprivate typealias setStatusBarStyleValueIMP = @convention(c) (NSObject, Selector, UIStatusBarStyle, Bool) -> Void
- #endif
- extension NSObject {
-
- typealias ThemePickers = [String: ThemePicker]
-
- var themePickers: ThemePickers {
- get {
- if let themePickers = objc_getAssociatedObject(self, &themePickersKey) as? ThemePickers {
- return themePickers
- }
- let initValue = ThemePickers()
- objc_setAssociatedObject(self, &themePickersKey, initValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- return initValue
- }
- set {
- objc_setAssociatedObject(self, &themePickersKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- _removeThemeNotification()
- if newValue.isEmpty == false { _setupThemeNotification() }
- }
- }
-
- func performThemePicker(selector: String, picker: ThemePicker?) {
- let sel = Selector(selector)
-
- guard responds(to: sel) else { return }
- guard let value = picker?.value() else { return }
-
- if let statePicker = picker as? ThemeStatePicker {
- let setState = unsafeBitCast(method(for: sel), to: setValueForStateIMP.self)
- statePicker.values.forEach {
-
- guard let value = $1.value() else {
- print("SwiftTheme WARNING: Missing value for ThemeStatePicker! Selector: \(String(describing: sel))")
- return
- }
- setState(self, sel, value as AnyObject, UIControl.State(rawValue: $0))
- }
- }
-
- else if let statusBarStylePicker = picker as? ThemeStatusBarStylePicker {
- #if os(iOS)
- let setStatusBarStyle = unsafeBitCast(method(for: sel), to: setStatusBarStyleValueIMP.self)
- setStatusBarStyle(self, sel, value as! UIStatusBarStyle, statusBarStylePicker.animated)
- #endif
- }
-
- else if picker is ThemeBarStylePicker {
- #if os(iOS)
- let setBarStyle = unsafeBitCast(method(for: sel), to: setBarStyleValueIMP.self)
- setBarStyle(self, sel, value as! UIBarStyle)
- #endif
- }
-
- else if picker is ThemeKeyboardAppearancePicker {
- let setKeyboard = unsafeBitCast(method(for: sel), to: setKeyboardValueIMP.self)
- setKeyboard(self, sel, value as! UIKeyboardAppearance)
- }
-
- else if picker is ThemeActivityIndicatorViewStylePicker {
- let setActivityStyle = unsafeBitCast(method(for: sel), to: setActivityStyleValueIMP.self)
- setActivityStyle(self, sel, value as! UIActivityIndicatorView.Style)
- }
-
- else if picker is ThemeScrollViewIndicatorStylePicker {
- let setIndicatorStyle = unsafeBitCast(method(for: sel), to: setScrollStyleValueIMP.self)
- setIndicatorStyle(self, sel, value as! UIScrollView.IndicatorStyle)
- }
-
- else if picker is ThemeCGFloatPicker {
- let setCGFloat = unsafeBitCast(method(for: sel), to: setCGFloatValueIMP.self)
- setCGFloat(self, sel, value as! CGFloat)
- }
-
- else if picker is ThemeCGColorPicker {
- let setCGColor = unsafeBitCast(method(for: sel), to: setCGColorValueIMP.self)
- setCGColor(self, sel, value as! CGColor)
- }
-
- else { perform(sel, with: value) }
- }
- }
- extension NSObject {
-
- fileprivate func _setupThemeNotification() {
- if #available(iOS 9.0, tvOS 9.0, *) {
- NotificationCenter.default.addObserver(self, selector: #selector(_updateTheme), name: NSNotification.Name(rawValue: ThemeUpdateNotification), object: nil)
- } else {
- NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: ThemeUpdateNotification), object: nil, queue: nil, using: { [weak self] notification in self?._updateTheme() })
- }
- }
-
- fileprivate func _removeThemeNotification() {
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: ThemeUpdateNotification), object: nil)
- }
-
- @objc private func _updateTheme() {
- themePickers.forEach { selector, picker in
- UIView.animate(withDuration: O2ThemeManager.animationDuration) {
- self.performThemePicker(selector: selector, picker: picker)
- }
- }
- }
-
- }
- private var themePickersKey = ""
|