Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize FluentTheme updating #1976

Merged
merged 4 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
14 changes: 8 additions & 6 deletions ios/FluentUI.Demo/FluentUI.Demo/BrandedSwitch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ class BrandedSwitch: UISwitch {
override init(frame: CGRect) {
super.init(frame: frame)

NotificationCenter.default.addObserver(forName: .didChangeTheme,
object: nil,
queue: nil) { [weak self] notification in
notificationObserver = NotificationCenter.default.addObserver(forName: .didChangeTheme,
object: nil,
queue: nil) { [weak self] notification in
guard let strongSelf = self,
let themeView = notification.object as? UIView,
strongSelf.isDescendant(of: themeView)
FluentTheme.isApplicableThemeChange(notification, for: strongSelf)
else {
return
}
strongSelf.onTintColor = themeView.fluentTheme.color(.brandForeground1)
strongSelf.onTintColor = strongSelf.fluentTheme.color(.brandForeground1)
}
}

Expand All @@ -34,4 +33,7 @@ class BrandedSwitch: UISwitch {
}
onTintColor = newWindow.fluentTheme.color(.brandForeground1)
}

/// Stores the notification handler for .didChangeTheme notifications.
private var notificationObserver: NSObjectProtocol?
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ColoredPillBackgroundView: UIView {
}

@objc func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, self.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: self) else {
return
}
updateBackgroundColor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class DemoListViewController: DemoTableViewController {
func updateColorProviderFor(window: UIWindow, theme: DemoColorTheme) {
self.theme = theme
if let provider = self.provider {
FluentTheme.setSharedThemeColorProvider(provider)
window.setColorProvider(provider)
let fluentTheme = self.view.fluentTheme
let primaryColor = fluentTheme.color(.brandBackground1)
FluentUIFramework.initializeAppearance(with: primaryColor, whenContainedInInstancesOf: [type(of: window)])
Expand Down
2 changes: 1 addition & 1 deletion ios/FluentUI/Calendar/CalendarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class CalendarView: UIView {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, self.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: self) else {
return
}
updateCollectionViewBackgroundColor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CalendarViewWeekdayHeadingView: UIView {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, self.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: self) else {
return
}
updateBackgroundColor()
Expand Down
2 changes: 1 addition & 1 deletion ios/FluentUI/Core/ControlHostingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ open class ControlHostingView: UIView {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, self.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: self) else {
return
}
updateRootView()
Expand Down
34 changes: 24 additions & 10 deletions ios/FluentUI/Core/Theme/FluentTheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,33 @@ public class FluentTheme: NSObject, ObservableObject {
@objc(sharedTheme)
public internal(set) static var shared: FluentTheme = FluentThemeKey.defaultValue {
didSet {
UIApplication.shared.connectedScenes
.compactMap {
$0 as? UIWindowScene
}
.flatMap {
$0.windows
}
.forEach { window in
NotificationCenter.default.post(name: .didChangeTheme, object: window)
}
NotificationCenter.default.post(name: .didChangeTheme, object: nil)
}
}

/// Determines if a given `Notification` should cause an update for the given `UIView`.
///
/// - Parameter notification: A `Notification` object that may be requesting a view update based on a theme change.
/// - Parameter view: The `UIView` instance that wants to determine whether to update.
///
/// - Returns: `True` if the view should update, `false` otherwise.
@objc(isApplicableThemeChangeNotification:forView:)
public static func isApplicableThemeChange(_ notification: Notification,
for view: UIView) -> Bool {
// Do not update unless the notification's name is `.didChangeTheme`.
guard notification.name == .didChangeTheme else {
mischreiber marked this conversation as resolved.
Show resolved Hide resolved
return false
}

// If there is no object, or it is not a UIView, we must assume that we need to update.
guard let themeView = notification.object as? UIView else {
return true
}

// If the object is a UIView, we only update if `view` is a descendant thereof.
return view.isDescendant(of: themeView)
}

// Token storage
let colorTokenSet: TokenSet<ColorToken, UIColor>
let shadowTokenSet: TokenSet<ShadowToken, ShadowInfo>
Expand Down
5 changes: 2 additions & 3 deletions ios/FluentUI/Core/Theme/Tokens/ControlTokenSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,12 @@ public class ControlTokenSet<T: TokenSetKey>: ObservableObject {
object: nil,
queue: nil) { [weak self, weak control] notification in
guard let strongSelf = self,
let themeView = notification.object as? UIView,
let control,
control.isDescendant(of: themeView)
FluentTheme.isApplicableThemeChange(notification, for: control)
else {
return
}
strongSelf.update(themeView.fluentTheme)
strongSelf.update(control.fluentTheme)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class DatePickerController: UIViewController, GenericDateTimePicker {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, view.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: view) else {
return
}
updateBackgroundColor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class DateTimePickerController: UIViewController, GenericDateTimePicker {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, view.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: view) else {
return
}
updateBackgroundColor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class DateTimePickerView: UIControl {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, self.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: self) else {
return
}
updateBackgroundColor()
Expand Down
2 changes: 1 addition & 1 deletion ios/FluentUI/People Picker/PersonaListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ open class PersonaListView: UITableView {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, self.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: self) else {
return
}
updateBackgroundColor()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ open class PageCardPresenterController: UIViewController {
}

@objc private func themeDidChange(_ notification: Notification) {
guard let themeView = notification.object as? UIView, view.isDescendant(of: themeView) else {
guard FluentTheme.isApplicableThemeChange(notification, for: view) else {
return
}
updatePageControlColors()
Expand Down
Loading