Closed defagos closed 3 years ago
Unlike view controller lifecycle methods, SwiftUI onAppear
method is called both when a view appears for the first time, as well as when it is revealed by dismissing another one. It therefore leads to undesired events when view controllers are revealed.
Fortunately, as SwiftUI internally makes use of UIKit, we can use standard view controller tracking to have the exact same behavior as we currently have for UIKit apps. For this to work the page view events must be forwarded correctly throughout the app implicit view controller hierarchy, which requires #45 to be implemented first.
Afterwards the strategy is quite simple:
UIViewControllerRepresentable
to wrap a dummy view controller conforming to SRGAnalyticsViewTracking
into a SwiftUI view. This tracking view inherits all tracking abilities of usual view controllers and correctly detects when a view is presented (nor revealed).SRGAnalyticsViewTracking
protocol for tracking SwiftUI views, we simply add a modifier which adds the tracking view as background view, effectively providing SwiftUI views with view controller-like appearance detection.This strategy works not only with mixed UIKit / SwiftUI apps, but also with pure SwiftUI apps (available since iOS / tvOS 14), which also have an internal view controller hierarchy (just call _printHierarchy
on the root view controller to see it).
Implemented on the feature/swiftui-page-view-tracking
branch.
We need a demo but this is really a task in itself (#47). A second target? A second project (with an additional xcconfig file to maintain)? For the moment I propose to go without, the code above can be easily tested with a pure SwiftUI app, e.g. with two tabs:
import SRGAnalytics
import SwiftUI
@main
struct TestSwiftUIApp: App {
init() {
let configuration = SRGAnalyticsConfiguration(businessUnitIdentifier: .RTS, container: 1012, siteName: "test", netMetrixIdentifier: "test")
SRGAnalyticsTracker.shared.start(with: configuration)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
and
import SRGAnalyticsSwiftUI
import SwiftUI
struct ContentView: View {
var body: some View {
TabView {
Text("Menu displayed here")
.tabItem {
Image(systemName: "list.dash")
Text("Menu")
}
.tracked(with: "menu")
Text("Orders displayed here")
.tabItem {
Image(systemName: "square.and.pencil")
Text("Order")
}
.tracked(with: "order")
}
}
}
We should an API for page view tracking of SwiftUI applications.