SwiftUIを調べているうちに、システム側で行っている処理が気になったので内部のClassについて調査しました。
今回調査したのはUIHostingController
の動作についてです。
UIHostingController
は_UIHostingView
をもつ
名前からある程度よそう可能ですが、UIHostingController
は_UIHostingView
をself.view
として保持しています。
_UIHostingView
class _UIHostinView: UIView {
var _rootView : ContentView
var viewGraph : ViewGraph
var viewUpdater : ViewUpdater
var eventBindingManager : EventBindingManager
var preferenceBridge : PreferenceBridge?
var currentTimestamp : Time
var needsRootViewUpdate : Bool
var needsEnvironmentUpdate : Bool
var updateDepth : Int
var isRendering : Bool
var postUpdateActions : Array<() -> ()>
var disabledBackgroundColor : Bool
var allowFrameChanges : Bool
var disableSafeArea : Bool
var safeAreaInsetsMask : Set
var previousSafeAreaInsets : UIEdgeInsets
var environmentOverride : EnvironmentValues?
var viewController : UIViewController?
var isAppRoot : Bool
var layoutTraitsDidChangeCallback : (_LayoutTraits, _LayoutTraits) -> ()?
var gestureRecognizer : UIKitGestureRecognizer
var displayLink : DisplayLink?
var lastRenderTime : Time
var needsDisplayLinkUpdate : Bool
var canAdvanceTimeAutomatically : Bool
var pendingPreferencesUpdate : Bool
var nextTimerTime : Time?
var updateTimer : NSTimer?
var skipped : Int
var colorScheme : ColorScheme?
var invertLayoutDirection : Bool
var navigationBridge : UIKitNavigationBridge<ContentView>
var alertBridge : AlertBridge<ContentView, Presentation>
var actionSheetBridge : AlertBridge<ContentView, Presentation>
var sheetBridge : SheetBridge<ContentView>
var popoverBridge : UIKitPopoverBridge<ContentView>
var statusBarHidden : Bool
var contextMenuBridge : ContextMenuBridge<ContentView>?
var accessibilityEnabled : Bool
var accessibilityNodes : Array<Any>
var accessibilityNeedsUpdate : Bool
var scrollTest : ScrollTest?
var delegate : UIHostingViewDelegate?
}
この中にあるscrollTest
非常に気になります。
Bridge
に注目
_UIHostingView
は、Bridge
を保持していました。
var preferenceBridge : PreferenceBridge?
var navigationBridge : UIKitNavigationBridge<ContentView>
var alertBridge : AlertBridge<ContentView, Presentation>
var actionSheetBridge : AlertBridge<ContentView, Presentation>
var sheetBridge : SheetBridge<ContentView>
var popoverBridge : UIKitPopoverBridge<ContentView>
var contextMenuBridge : ContextMenuBridge<ContentView>?
PreferenceBridge
をおいて、そのほかはViewの遷移に必要なインスタンスを保持しているようです。
Bridge
について調べてみた
navigationBridge
class UIKitNavigationBridge<ContentView> {
var host : _UIHostingView<ContentView>?
var hasNavigationItem : Bool
var activePresentation : BridgedPresentation?
var destinations : Value<Dictionary<ViewIdentity, NavigationDestinationContent>>
var lastEnvironment : EnvironmentValues
var tableViewRegistry : TableViewRegistry
var isNavigationBarHidden : Bool
var containingNavControllerOverride : UINavigationController?
}
alertBridge
class AlertBridge<ContentView, Presentation> {
var host : _UIHostingView<ContentView>?
var isShown : Bool
var seed : VersionSeed
var alertController : UIAlertController?
var lastEnvironment : EnvironmentValues
var lastPresentation : Presentation?
var style : UIAlertControllerStyle
}
actionSheetBridge
class AlertBridge<ContentView, Presentation> {
var host : _UIHostingView<ContentView>?
var isShown : Bool
var seed : VersionSeed
var alertController : UIAlertController
var lastEnvironment : EnvironmentValues
var lastPresentation : Presentation?
var style : UIAlertControllerStyle
}
sheetBridge
class SheetBridge<ContentView> {
var host : _UIHostingView<ContentView>?
var seed : VersionSeed
var isShown : Bool
var presentedVC : SheetHostingController<AnyView>?
var lastPresentation : SheetPreference?
var lastEnvironment : EnvironmentValues
}
popoverBridge
class UIKitPopoverBridge<ContentView> {
var host : _UIHostingView<ContentView>?
var isShown : Bool
var seed : VersionSeed
var presentedVC : UIHostingController<AnyView>?
var lastPresentation : PopoverPresentation?
}
EnvironmentValues
lastEnvironment
ならアクセスできそうなので中身をみてみた
[
EnvironmentPropertyKey<TableViewRegistryKey> = Optional(SwiftUI.TableViewRegistry),
EnvironmentPropertyKey<NavigationStateKey> = nil,
EnvironmentPropertyKey<PresentationModeKey> = Binding<PresentationMode>(transaction: SwiftUI.Transaction(plist: []), location: SwiftUI.LocationBox<SwiftUI.FunctionalLocation<SwiftUI.PresentationMode>>, _value: SwiftUI.PresentationMode(isPresented: false)),
EnvironmentPropertyKey<ActiveContextMenuKey> = ViewIdentity(seed: 0),
EnvironmentPropertyKey<ColorSchemeKey> = light,
EnvironmentPropertyKey<AccentColorKey> = Optional(#007AFFFF),
EnvironmentPropertyKey<UndoManagerKey> = Optional(<NSUndoManager: 0x60000243ac10>),
EnvironmentPropertyKey<AccessibilityInvertColorsKey> = false,
EnvironmentPropertyKey<AccessibilityReduceMotionKey> = false,
EnvironmentPropertyKey<AccessibilityReduceTransparencyKey> = false,
EnvironmentPropertyKey<AccessibilityDifferentiateWithoutColorKey> = false,
EnvironmentPropertyKey<BackgroundInfoKey> = BackgroundInfo(layer: 0, groupCount: 0),
EnvironmentPropertyKey<VerticalUserInterfaceSizeClassKey> = Optional(SwiftUI.UserInterfaceSizeClass.regular),
EnvironmentPropertyKey<HorizontalUserInterfaceSizeClassKey> = Optional(SwiftUI.UserInterfaceSizeClass.compact),
EnvironmentPropertyKey<DisplayScaleKey> = 3.0,
EnvironmentPropertyKey<ColorSchemeContrastKey> = standard,
EnvironmentPropertyKey<LegibilityWeightKey> = Optional(SwiftUI.LegibilityWeight.regular),
EnvironmentPropertyKey<PreferredContentSizeCategoryKey> = large, EnvironmentPropertyKey<LayoutDirectionKey> = leftToRight,
EnvironmentPropertyKey<LocaleKey> = en (current)
]