11//
2- // ImageClassPicker .swift
2+ // ImageRuntimeObjectsView .swift
33// HeaderViewer
44//
55// Created by Leptos on 2/20/24.
@@ -15,7 +15,7 @@ private enum ImageLoadState {
1515 case loadError( Error )
1616}
1717
18- private class ImageClassPickerModel : ObservableObject {
18+ private class ImageRuntimeObjectsViewModel : ObservableObject {
1919 let namedNode : NamedNode
2020
2121 let imagePath : String
@@ -24,13 +24,21 @@ private class ImageClassPickerModel: ObservableObject {
2424 let runtimeListings : RuntimeListings = . shared
2525
2626 @Published var searchString : String
27+ @Published var searchScope : RuntimeTypeSearchScope
2728
2829 @Published private( set) var classNames : [ String ] // not filtered
30+ @Published private( set) var protocolNames : [ String ] // not filtered
2931 @Published private( set) var runtimeObjects : [ RuntimeObjectType ] // filtered based on search
3032 @Published private( set) var loadState : ImageLoadState
3133
32- private static func runtimeObjectsFor( classNames: [ String ] , searchString: String ) -> [ RuntimeObjectType ] {
33- let ret : [ RuntimeObjectType ] = classNames. map { . class( named: $0) }
34+ private static func runtimeObjectsFor( classNames: [ String ] , protocolNames: [ String ] , searchString: String , searchScope: RuntimeTypeSearchScope ) -> [ RuntimeObjectType ] {
35+ var ret : [ RuntimeObjectType ] = [ ]
36+ if searchScope. includesClasses {
37+ ret += classNames. map { . class( named: $0) }
38+ }
39+ if searchScope. includesProtocols {
40+ ret += protocolNames. map { . protocol( named: $0) }
41+ }
3442 if searchString. isEmpty { return ret }
3543 return ret. filter { $0. name. localizedCaseInsensitiveContains ( searchString) }
3644 }
@@ -43,12 +51,20 @@ private class ImageClassPickerModel: ObservableObject {
4351 self . imageName = namedNode. name
4452
4553 let classNames = CDUtilities . classNamesIn ( image: imagePath)
54+ let protocolNames = runtimeListings. imageToProtocols [ CDUtilities . patchImagePathForDyld ( imagePath) ] ?? [ ]
4655 self . classNames = classNames
56+ self . protocolNames = protocolNames
4757
4858 let searchString = " "
59+ let searchScope : RuntimeTypeSearchScope = . all
60+
4961 self . searchString = searchString
62+ self . searchScope = searchScope
5063
51- self . runtimeObjects = Self . runtimeObjectsFor ( classNames: classNames, searchString: searchString)
64+ self . runtimeObjects = Self . runtimeObjectsFor (
65+ classNames: classNames, protocolNames: protocolNames,
66+ searchString: searchString, searchScope: searchScope
67+ )
5268
5369 self . loadState = runtimeListings. isImageLoaded ( path: imagePath) ? . loaded : . notLoaded
5470
@@ -58,13 +74,23 @@ private class ImageClassPickerModel: ObservableObject {
5874 }
5975 . assign ( to: & $classNames)
6076
77+ runtimeListings. $imageToProtocols
78+ . map { imageToProtocols in
79+ imageToProtocols [ CDUtilities . patchImagePathForDyld ( imagePath) ] ?? [ ]
80+ }
81+ . assign ( to: & $protocolNames)
82+
6183 let debouncedSearch = $searchString
6284 . debounce ( for: 0.08 , scheduler: RunLoop . main)
6385
64- $classNames. combineLatest ( debouncedSearch) { classNames, searchString in
65- Self . runtimeObjectsFor ( classNames: classNames, searchString: searchString)
66- }
67- . assign ( to: & $runtimeObjects)
86+ $searchScope
87+ . combineLatest ( debouncedSearch, $classNames, $protocolNames) {
88+ Self . runtimeObjectsFor (
89+ classNames: $2, protocolNames: $3,
90+ searchString: $1, searchScope: $0
91+ )
92+ }
93+ . assign ( to: & $runtimeObjects)
6894
6995 runtimeListings. $imageList
7096 . map { imageList in
@@ -88,12 +114,12 @@ private class ImageClassPickerModel: ObservableObject {
88114 }
89115}
90116
91- struct ImageClassPicker : View {
92- @StateObject private var viewModel : ImageClassPickerModel
117+ struct ImageRuntimeObjectsView : View {
118+ @StateObject private var viewModel : ImageRuntimeObjectsViewModel
93119 @Binding private var selection : RuntimeObjectType ?
94120
95121 init ( namedNode: NamedNode , selection: Binding < RuntimeObjectType ? > ) {
96- _viewModel = StateObject ( wrappedValue: ImageClassPickerModel ( namedNode: namedNode) )
122+ _viewModel = StateObject ( wrappedValue: ImageRuntimeObjectsViewModel ( namedNode: namedNode) )
97123 _selection = selection
98124 }
99125
@@ -115,19 +141,16 @@ struct ImageClassPicker: View {
115141 ProgressView ( )
116142 . scenePadding ( )
117143 case . loaded:
118- if viewModel. classNames. isEmpty {
144+ if viewModel. classNames. isEmpty && viewModel . protocolNames . isEmpty {
119145 StatusView {
120- Text ( " \( viewModel. imageName) is loaded however does not appear to contain any classes " )
146+ Text ( " \( viewModel. imageName) is loaded however does not appear to contain any classes or protocols " )
121147 . padding ( . top)
122148 }
123149 } else {
124- let runtimeObjects = viewModel. runtimeObjects
125- ListView ( runtimeObjects, selection: $selection) { runtimeObject in
126- RuntimeObjectRow ( type: runtimeObject)
127- }
128- . id ( runtimeObjects) // don't try to diff the List
129- . searchable ( text: $viewModel. searchString)
130- . autocorrectionDisabled ( ) // turn of auto-correct for the search field
150+ RuntimeObjectsList (
151+ runtimeObjects: viewModel. runtimeObjects, selectedObject: $selection,
152+ searchString: $viewModel. searchString, searchScope: $viewModel. searchScope
153+ )
131154 }
132155 case . loadError( let error) :
133156 StatusView {
0 commit comments