ForEach 完成时执行代码 - swiftUI

Posted

技术标签:

【中文标题】ForEach 完成时执行代码 - swiftUI【英文标题】:Execute code when ForEach finish - swiftUI 【发布时间】:2021-11-19 10:32:26 【问题描述】:

我想知道是否有一种方法可以在 forEach 函数完成事件上执行给定代码(如 OnAppear 或苹果提供的类似方法),如果没有可用的方法,我如何在 ForEach 完成时执行代码。

我有以下代码:

ScrollView 
    ScrollViewReader  value in
        VStack  
            let tweets = getFilteredTweets()
            ForEach((0..<tweets.count), id: \.self)  index in
                NavigationLink(destination: TweetWebView(
                    tweetId: tweets[index].id,
                    accountId: self.viewModel.viewState.selectedAccounts.first(where: 
                        $0.screenName == tweets[index].screenName
                    )?.screenName?.lowercased()
                )) 
                    VStack 
                        TweetView(
                            style: .withNoImage,
                            withHeight: true,
                            account: self.viewModel.viewState.selectedAccounts.first(where: 
                                $0.screenName == tweets[index].screenName
                            ),
                            tweet: tweets[index]
                        )
                            .frame(maxHeight: .infinity)
                            .onTapGesture 
                                viewModel.triggerEvent(.setTweetSelectedIndex(index: index))
                            
                    
                
                .buttonStyle(PlainButtonStyle())
            
            .onAppear 
                value.scrollTo(viewModel.viewState.tweetSelectedIndex ?? 0)
            
        
    

我要在事件 ForEach 完成时执行的代码:

value.scrollTo(viewModel.viewState.tweetSelectedIndex ?? 0)

【问题讨论】:

回答你的问题,没有。然而,这需要一个Minimal, Reproducible Example,但你可能会在scrollTo 周围有一个DispatchQueue.main.asyncAfter(deadline:)。你没有说实际发生了什么,但我怀疑你的 scrollTo 没有像你预期的那样滚动。我认为你在这里有一个 XY 问题。你想做 X,你认为 Y 是解决方案。你不能让 Y 工作,所以当你真的想解决 X 时,你发布关于 Y 的信息。Y 是在 ForEach 完成后运行代码。 最后是主观的。 for each 不一定会一次加载所有对象。有许多因素会影响预加载的项目数量。需要考虑的事情是反转数组。在顶部为您提供最新信息。 【参考方案1】:

ForEach 没有任何自己的外观。它代表视图的集合,由ForEach 的容器决定如何显示该集合。那么onAppear 附加到ForEach 时意味着什么?它会流向集合中的每个视图吗?最好避免依赖这种奇怪组合的行为。

改为将onAppear 附加到包含VStack

scrollTo 方法采用您给它的id(在本例中为viewModel.viewState.tweetSelectedIndex ?? 0)并尝试查找具有相同标识符的id 修饰符的视图。但是您还没有将id 修饰符放在ScrollView 中的任何视图上。你需要使用id修饰符:

ScrollView 
    ScrollViewReader  value in
        VStack  
            let tweets = getFilteredTweets()
            ForEach(0 ..< tweets.count, id: \.self)  index in
                NavigationLink(destination: TweetWebView(
                    tweetId: tweets[index].id,
                    accountId: self.viewModel.viewState.selectedAccounts.first(where: 
                        $0.screenName == tweets[index].screenName
                    )?.screenName?.lowercased()
                )) 
                    // blah blah blah
                
                .buttonStyle(PlainButtonStyle())
                .id(index)
// ADD THIS     ^^^^^^^^^^
            
        
        .onAppear 
//      ^^^^^^^^^    MOVE THIS ONTO THE VSTACK
            value.scrollTo(viewModel.viewState.tweetSelectedIndex ?? 0)
        
    

【讨论】:

以上是关于ForEach 完成时执行代码 - swiftUI的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 中的 ForEach

如何在 SwiftUI 的 ForEach 循环中增加状态?

SwiftUI 中按钮操作内的 ForEach 循环?

SwiftUI:Firebase ForEach 列表执行编辑功能无法编辑选定的行项目

为 ForEach 循环元素添加动画 (SwiftUI)

SwiftUI:当 List 和 ForEach 嵌入 TabView 时 WatchOS 8.1 中的 NavigationView 错误