I have this issue with pull to refresh & navigation bar. The problem is that the navigation title jumps back to top as soon as refresh is done(without user actually releasing pull to refresh).
Is it possible to avoid? Don't remember having this issue with UIKit.
Here is what happens:
Here is my ViewModel code that handles the data refresh:
@Published var alerts: [Alert] = []
....
func refresh() async {
do {
let result = try await repository.fetchAlerts(page: 1, perPage: 20)
alerts = result.items
} catch {
showErrorBanner(error)
}
}
View:
struct AlertsView: View {
@StateObject private var viewModel = AlertsViewModel()
@StateObject private var navigationManager = NavigationManager<AppRoutes>()
var body: some View {
NavigationStack(path: $navigationManager.path) {
ScrollView {
LazyVStack(alignment: .leading) {
ForEach(viewModel.alerts) { alert in
Text(alert.body)
}
}
}
.refreshable {
await viewModel.refresh()
}
.navigationTitle("Alerts")
.navigationBarTitleDisplayMode(.large)
}
.environmentObject(navigationManager)
}
}
Thought maybe it's just my frontend code messing with it, but it happens even with a simple layout(without any styles): NavigationStack - ScrollView - LazyVStack - ForEach - Text.
EDIT: This issue only happens with navigationBarTitleDisplayMode
set to .large
. .inline
works fine...
Min. deployment target is set to iOS16.
EDIT: Looks like if try await Task.sleep(for: .seconds(1))
is added before the API call it kinda works fine.
@Published var alerts: [Alert] = []
....
func refresh() async {
do {
try await Task.sleep(for: .seconds(1)) <--- HERE
let result = try await repository.fetchAlerts(page: 1, perPage: 20)
alerts = result.items
} catch {
showErrorBanner(error)
}
}