Posted at

[SwiftUI]生成されたUIViewを直接操作する

これは実験的な話です。

次のようなRootViewで構築したビューはUIKitのビューヒエラルキーにUITableViewが含まれているはずです。


struct Message: Identifiable {
let id: Int
}

struct ContentView: View {
@State var messages: [Message] = (0..<100).map({ Message(id: $0) })

var body: some View {
List {
ForEach(messages, id: \.id) {
Text("\($0.id)")
}
}
}
}

スクリーンショット 2019-10-12 4.22.27.png

このUITableViewを直接参照して操作出来るのか試してみます。

まずはビューヒエラルキをダンプ

Optional(<UIWindow: 0x7fe6e5b25710; frame = (0 0; 414 896); gestureRecognizers = <NSArray: 0x60000286df80>; layer = <UIWindowLayer: 0x600002633c40>>)

Optional(Swift.Unmanaged<Swift.AnyObject>(_value: <UITransitionView: 0x7fe6e371abd0; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x60000260a400>>
| <UIDropShadowView: 0x7fe6e371ba30; frame = (0 0; 414 896); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x60000260a920>>
| | <_TtGC7SwiftUI14_UIHostingViewV6Scroll11ContentView_: 0x7fe6e370c4a0; frame = (0 0; 414 896); autoresize = W+H; gestureRecognizers = <NSArray: 0x60000284ccf0>; layer = <CALayer: 0x600002637e20>>
| | | <_TtGC7SwiftUI16PlatformViewHostGVS_P13$7fff2c6cf80432PlatformViewRepresentableAdaptorGVS_P13$7fff2c69c16c9_ListCoreGVS_20SystemListDataSourceOs5Never_GOS_19SelectionManagerBoxS4_____: 0x7fe6e5b2b220; frame = (0 0; 414 896); anchorPoint = (0, 0); tintColor = UIExtendedSRGBColorSpace 0 0.478431 1 1; layer = <CALayer: 0x600002606220>>
| | | | <_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView: 0x7fe6e5029c00; baseClass = UITableView; frame = (0 0; 414 896); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x600002841470>; layer = <CALayer: 0x600002604220>; contentOffset: {0, -44}; contentSize: {414, 4406.666666666667}; adjustedContentInset: {44, 0, 34, 0}; dataSource: <_TtGC7SwiftUIP13$7fff2c69bad819ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_GOS_19SelectionManagerBoxS2___: 0x7fe6e3605c80>>
| | | | | <SwiftUI.ListCoreCellHost: 0x7fe6e3731c20; baseClass = UITableViewCell; frame = (0 1330; 414 44.3333); autoresize = W; layer = <CALayer: 0x60000267b620>>
| | | | | | <UITableViewCellContentView: 0x7fe6e3731fe0; frame = (0 0; 414 44.3333); gestureRecognizers = <NSArray: 0x600002887450>; layer = <CALayer: 0x60000267b960>>
| | | | | | | <_TtGC7SwiftUI17UIItemHostingViewGVS_15ModifiedContentGS1_VS_14_ViewList_ViewVVS_17CellForRowVisitor12CellModifier_VS_19DisappearedModifier__: 0x7fe6e3732330; frame = (0 0; 414 44.3333); autoresize = W+H; gestureRecognizers = <NSArray: 0x6000028a32a0>; layer = <CALayer: 0x600002675b60>>
| | | | | | | | <_TtCOCV7SwiftUI11DisplayList11ViewUpdater8Platform13CGDrawingView: 0x7fe6e3628bf0; frame = (16 12; 20.6667 20.3333); anchorPoint = (0, 0); opaque = NO; autoresizesSubviews = NO; layer = <CALayer: 0x60000264fe00>>
....

_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableViewが怪しそうなので、キャストしてscrollToRowを呼んでみます。


if let tableView = window.rootViewController?.view.subviews[0].subviews[0] as? UITableView {
tableView.scrollToRow(at: .init(row: 10, section: 0), at: .top, animated: true)
}

名称未設定.gif

呼べました。