SwiftUI +可刷新:拉取刷新时,大导航标题会跳转

8qgya5xd  于 2023-06-21  发布在  Swift
关注(0)|答案(1)|浏览(85)

我有这个问题与拉刷新和导航栏。问题是,导航标题跳回到顶部,只要刷新完成(没有用户实际释放拉刷新)。
有可能避免吗?不记得UIKit有这个问题。
以下是发生的情况:

下面是处理数据刷新的ViewModel代码:

@Published var alerts: [Alert] = []

    ....

    func refresh() async {
        do {
            let result = try await repository.fetchAlerts(page: 1, perPage: 20)
            alerts = result.items
        } catch {
            showErrorBanner(error)
        }
    }

浏览次数:

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)
    }
}

我想可能是我的前端代码搞砸了,但即使是简单的布局(没有任何样式)也会发生这种情况:NavigationStack - ScrollView - LazyVStack - ForEach - Text。
编辑:此问题仅在navigationBarTitleDisplayMode设置为.large时发生。.inline工作正常...
最小部署目标设置为iOS 16。
编辑:看起来如果在API调用之前添加try await Task.sleep(for: .seconds(1)),它会工作得很好。

@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)
        }
    }
g6ll5ycj

g6ll5ycj1#

我有问题与拉刷新(因为我有一个自定义的头),并能够找到一个自定义拉刷新,工程真的很好。我认为这可能是SwiftUI可刷新修改器中的一个小故障。

import SwiftUI

struct PullToRefresh: View {
    
    var coordinateSpaceName: String
    var onRefresh: ()->Void
    
    @State var needRefresh: Bool = false
    
    var body: some View {
        GeometryReader { geo in
            if (geo.frame(in: .named(coordinateSpaceName)).midY > 50) {
                Spacer()
                    .onAppear {
                        needRefresh = true
                    }
            } else if (geo.frame(in: .named(coordinateSpaceName)).maxY < 10) {
                Spacer()
                    .onAppear {
                        if needRefresh {
                            needRefresh = false
                            onRefresh()
                        }
                    }
            }
            HStack {
                Spacer()
                if needRefresh {
                    ProgressView()
                }
// You can uncomment this if you want to see where this is occurring in your View 
//                else {
//                    Text("⬇️")
//                }
                Spacer()
            }
        }.padding(.top, -50)
    }
}

我通过添加.coordinateSpace(name:“pullToRefresh”),然后将自定义PullToRefresh插入到我的ScrollView中

PullToRefresh(coordinateSpaceName: "pullToRefresh") {
 // These functions are the ones I want my viewModel to execute. For example, I want to shuffle the images that appear on the home page when the page is refreshed. 
                            viewModel.styles.shuffle()
                            viewModel.posts.shuffle()
                            viewModel.brands.shuffle()
                        }

相关问题