@@ -30,9 +30,16 @@ internal struct SwiftUIReflectionBasedViewNameExtractor: SwiftUIViewNameExtracto
30
30
self . createReflector = reflectorFactory
31
31
}
32
32
33
- /// Attempts to extract a meaningful SwiftUI view name from a UIViewController
33
+ /// Convenience initializer
34
+ init ( telemetry: Telemetry ) {
35
+ self . init ( reflectorFactory: { subject in
36
+ Reflector ( subject: subject, telemetry: telemetry)
37
+ } )
38
+ }
39
+
40
+ /// Attempts to extract a meaningful SwiftUI view name from a `UIViewController`
34
41
/// - Parameter viewController: The `UIViewController` potentially hosting a SwiftUI view
35
- /// - Returns: The extracted view name or nil if extraction failed
42
+ /// - Returns: The extracted view name or ` nil` if extraction failed
36
43
func extractName( from viewController: UIViewController ) -> String ? {
37
44
// Skip known container controllers that shouldn't be tracked
38
45
if shouldSkipViewController ( viewController: viewController) {
@@ -64,6 +71,10 @@ internal struct SwiftUIReflectionBasedViewNameExtractor: SwiftUIViewNameExtracto
64
71
return extractViewName ( from: typeDescription ( of: output) )
65
72
}
66
73
74
+ if let output = SwiftUIViewPath . hostingControllerRoot. traverse ( with: reflector) {
75
+ return extractViewName ( from: typeDescription ( of: output) )
76
+ }
77
+
67
78
case . navigationController:
68
79
// Try detail view first
69
80
if let output = SwiftUIViewPath . navigationStackDetail. traverse ( with: reflector) {
@@ -93,30 +104,32 @@ internal struct SwiftUIReflectionBasedViewNameExtractor: SwiftUIViewNameExtracto
93
104
}
94
105
95
106
// MARK: - Helpers
96
- /// Extracts a view name from a type description using regex patterns
97
- internal func extractViewName( from input: String ) -> String ? {
98
- // Pattern 1: Extract the view name from generic types like LazyView<ContentView>
99
- let simpleGenericPattern = #"<([^<>,]+)>"#
100
- if let match = input. range ( of: simpleGenericPattern, options: . regularExpression) {
101
- let startIndex = input. index ( match. lowerBound, offsetBy: 1 )
102
- let endIndex = input. index ( match. upperBound, offsetBy: - 1 )
103
- return String ( input [ startIndex..< endIndex] )
107
+ private static let genericTypePattern : NSRegularExpression ? = {
108
+ do {
109
+ return try NSRegularExpression ( pattern: #"<(?:[^,>]*,\s+)?([^<>,]+?)>"# )
110
+ } catch {
111
+ return nil
104
112
}
113
+ } ( )
105
114
106
- // Pattern 2: Extract the view name from complex generic types like ParameterizedLazyView<String, DetailView>
107
- let complexGenericPattern = #"<.*,\s*([^<>,]+)>"#
108
- if let match = input. range ( of: complexGenericPattern, options: . regularExpression) ,
109
- let captureRange = input. range ( of: #"([^<>,]+)(?=>)"# , options: . regularExpression, range: match) {
110
- return String ( input [ captureRange] ) . trimmingCharacters ( in: . whitespaces)
115
+ /// Extracts a view name from a type description
116
+ internal func extractViewName( from input: String ) -> String ? {
117
+ // Extract the view name from generic types like ParameterizedLazyView<String, DetailView>
118
+ if let match = Self . genericTypePattern? . firstMatch (
119
+ in: input,
120
+ options: [ ] ,
121
+ range: NSRange ( input. startIndex..< input. endIndex, in: input)
122
+ ) ,
123
+ let range = Range ( match. range ( at: 1 ) , in: input) {
124
+ return String ( input [ range] )
111
125
}
112
126
113
- // Pattern 3: Extract the view name from metatypes like DetailView.Type
127
+ // Extract the view name from metatypes like DetailView.Type
114
128
if input. hasSuffix ( " .Type " ) {
115
129
return String ( input. dropLast ( 5 ) )
116
130
}
117
131
118
- // Return the input as a fallback
119
- return input
132
+ return nil
120
133
}
121
134
122
135
private func extractTabViewName( from viewController: UIViewController ) -> String ? {
0 commit comments