SwiftUI中Refreshable Indicator视图出现时自动显示的问题
问题:Refreshable Indicator在视图加载时自动显示(仅iOS 16.1物理设备+inline导航栏)
现象与环境
- 视图出现时,
Refreshable Indicator自动显示,无需下拉列表;上滑列表后指示器隐藏,后续下拉刷新功能可正常执行(显示、操作、隐藏) - 仅在iPhone 13 Pro Max(iOS 16.1)物理设备上复现,同版本模拟器无此问题
- 触发条件:仅当
navigationBarTitleDisplayMode设置为.inline时出现,使用默认.large时无此问题 - 已尝试无效操作:调整
.refreshable修饰符顺序、修改.listStyle
相关代码
struct OrdersView: View { @EnvironmentObject private var tabBarStateManager: TabBarStateManager @EnvironmentObject private var profileViewModel: ProfileViewModel @StateObject private var ordersViewModel: OrdersViewModel = OrdersViewModel() @Environment(\.dismiss) private var dismiss: DismissAction var body: some View { List { ForEach(ordersViewModel.datesForOrdersViewListSections, id: \.self) { stringDate in Section { ForEach(ordersViewModel.getOrdersFor(date: stringDate), id: \.self) { order in NavigationLink(destination: OrderDetailsView(order: order, orderProductsList: ordersViewModel.getOrderProductsFor(order: order)) .environmentObject(ordersViewModel)) { VStack(alignment: .leading, spacing: 20) { HStack(spacing: 10) { Text(order.id) .font(.ssCallout) Spacer() Text(Date.getDayAndMonthFrom(date: order.orderDate)) .font(.ssTitle3) .foregroundColor(.accentColor) } Text("\(order.totalCost, specifier: \"%.2f\")") .font(.ssTitle3) .foregroundColor(.accentColor) VStack(alignment: .leading) { HStack { Text(TexterifyManager.localisedString(key: .ordersView(.products))) .font(.ssCallout) Text("\(ordersViewModel.getOrderProductsFor(order: order).count)") .font(.ssTitle3) .foregroundColor(.accentColor) } HStack { Text(TexterifyManager.localisedString(key: .ordersView(.orderStatus))) .font(.ssCallout) Text(order.status.rawValue) .font(.ssTitle3) .foregroundColor(.accentColor) } } } .padding(.vertical) } } } header: { Text(stringDate) .font(.ssTitle1) .foregroundColor(.accentColor) } } } .listStyle(.grouped) .refreshable { profileViewModel.fetchUserOrders { ordersViewModel.userOrders = profileViewModel.userOrders } } .navigationTitle(TexterifyManager.localisedString(key: .ordersView(.navigationTitle))) .navigationBarTitleDisplayMode(.inline) .navigationBarBackButtonHidden(true) .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button { dismiss() } label: { Image(systemName: "arrow.backward.circle.fill") .resizable() .frame(width: 30, height: 30) .foregroundColor(.accentColor) } } } .onAppear { ordersViewModel.userOrders = profileViewModel.userOrders } } }
解决方案建议
1. 手动重置滚动位置(快速临时修复)
在onAppear中延迟执行滚动到顶部的操作,强制隐藏自动弹出的指示器:
.onAppear { ordersViewModel.userOrders = profileViewModel.userOrders // 延迟0.1秒执行,确保视图已完成布局 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { UIScrollView.appearance().setContentOffset(.zero, animated: false) } }
如果不想全局修改UIScrollView,也可以用ScrollViewReader控制当前List的滚动:
// 先在结构体里添加状态变量 @State private var scrollProxy: ScrollViewProxy? // 给List添加scrollViewReader修饰 List { // ...原有列表内容 } .scrollViewReader { proxy in scrollProxy = proxy } // 修改onAppear .onAppear { ordersViewModel.userOrders = profileViewModel.userOrders DispatchQueue.main.async { withAnimation(.easeInOut(duration: 0.1)) { scrollProxy?.scrollTo(nil, anchor: .top) } } }
2. 调整.refreshable的修饰位置
将.refreshable从List移到外层的Navigation容器上(适用于iOS 16+的NavigationStack):
NavigationStack { List { // ...原有列表内容 } .listStyle(.grouped) .navigationTitle(TexterifyManager.localisedString(key: .ordersView(.navigationTitle))) .navigationBarTitleDisplayMode(.inline) // ...其他导航栏相关修饰 } .refreshable { profileViewModel.fetchUserOrders { ordersViewModel.userOrders = profileViewModel.userOrders } }
3. 升级iOS系统版本
该问题属于iOS 16.1的已知兼容性bug,升级到iOS 16.2及以上版本后,苹果官方已修复类似的导航栏与下拉刷新冲突问题,建议优先测试新版本系统是否解决问题。
内容的提问来源于stack exchange,提问作者Vader20FF
相关产品推荐
相关产品推荐

