Signal-Pods/BonMot/Sources/UIKit/UIKit+AdaptableTextContainerSupport.swift
2021-08-16 12:12:57 -10:00

86 lines
3.6 KiB
Swift

//
// UIKit+AdaptableTextContainerSupport.swift
// BonMot
//
// Created by Brian King on 7/19/16.
// Copyright © 2016 Rightpoint. All rights reserved.
//
#if canImport(UIKit) && !os(watchOS)
import UIKit
extension UIApplication {
/// Support for the `AdaptableTextContainer` protocol is enabled with this
/// method. It adds the application as an observer for `UIContentSizeCategoryDidChangeNotification`
/// and floods the change notification to the `UIViewController` hierarchy,
/// which by default floods the view managed by each `UIViewController`.
///
/// The `UIApplication` delegate is also checked for conformance to
/// `AdaptableTextContainer`, which can be a good place to update appearance
/// proxies and invalidate any hard-wired caches that less responsive code may have.
public final func enableAdaptiveContentSizeMonitor() {
let notificationCenter = NotificationCenter.default
let notificationName = UIContentSizeCategory.didChangeNotification
notificationCenter.addObserver(
self,
selector: #selector(UIApplication.bon_notifyContainedAdaptiveContentSizeContainers(fromNotification:)),
name: notificationName,
object: nil)
}
// Notify the view controller hierarchy.
@objc internal func bon_notifyContainedAdaptiveContentSizeContainers(fromNotification notification: NSNotification) {
// First notify the app delegate if it conforms to AdaptableTextContainer.
if let container = delegate, let traitCollection = container.window??.traitCollection {
if container.responds(to: #selector(AdaptableTextContainer.adaptText(forTraitCollection:))) {
container.perform(#selector(AdaptableTextContainer.adaptText(forTraitCollection:)), with: traitCollection)
}
}
for window in windows {
// Notify all views in the view hierarchy
window.notifyContainedAdaptiveContentSizeContainers()
// Notify all of the view controllers
window.rootViewController?.notifyContainedAdaptiveContentSizeContainers()
}
}
}
extension UIViewController {
/// 1. If the view is loaded and not installed in the view hierarchy, notify
/// the receiver's view and subviews. If the view is in the view hierarchy,
/// it has already been notified, so do not notify again.
/// 2. Then notify all child view controllers, then the presented view controller, if any.
final func notifyContainedAdaptiveContentSizeContainers() {
if let view = viewIfLoaded {
if view.window == nil {
view.notifyContainedAdaptiveContentSizeContainers(with: traitCollection)
}
}
for viewController in children {
viewController.notifyContainedAdaptiveContentSizeContainers()
}
presentedViewController?.notifyContainedAdaptiveContentSizeContainers()
adaptText(forTraitCollection: traitCollection)
}
}
extension UIView {
/// Notify any subviews, then notify the receiver if it conforms to `AdaptableTextContainer`.
final func notifyContainedAdaptiveContentSizeContainers(with traitCollection: UITraitCollection? = nil) {
for view in subviews {
view.notifyContainedAdaptiveContentSizeContainers(with: traitCollection ?? self.traitCollection)
}
if responds(to: #selector(AdaptableTextContainer.adaptText(forTraitCollection:))) {
perform(#selector(AdaptableTextContainer.adaptText(forTraitCollection:)), with: traitCollection)
}
}
}
#endif