首页 > 解决方案 > 自动选择 SwiftUI 中的第 0 个项目

问题描述

我已将数据加载到HStackinScroll ViewSwiftUI。现在我已经对其进行了编码,用户可以在其中点击这些项目之一并选择它。我希望在加载时已经选择了第 0 个项目。

import SwiftUI
import Combine
import Contentful

struct moviesView : View {

    @ObservedObject var fetcher = MovieFetcher()

    @State var selectMovie: Movie? = nil

    @Binding var show: Bool

    var body: some View {
        HStack(alignment: .bottom) {
            if show {
                ScrollView(.horizontal) {
                    Spacer()

                    HStack(alignment: .bottom, spacing: 30) {
                        ForEach(fetcher.movies, id: \.self) { item in
                            selectableRow(movie: item, selectMovie: self.$selectMovie)
                        }
                        .onAppear() {
                            self.selectMovie = self.movies.count > 0 ? self.movies.first! : nil
                        }
                    }
                    .frame(minWidth: 0, maxWidth: .infinity)
                }
                .padding(.leading, 46)
                .padding(.bottom, 26)
            }
        }
    }
}

struct selectableRow : View {

    var movie: Movie

    @Binding var selectedMovie: Movie?

    @State var initialImage = UIImage()

    var body: some View {
        ZStack(alignment: .center) {
            if movie == selectedMovie {
                Image("")
                .resizable()
                .frame(width: 187, height: 254)
                .overlay(
                    RoundedRectangle(cornerRadius: 13)
                Image(uiImage: initialImage)
                .resizable()
                .cornerRadius(13.0)
                .frame(width: 182, height: 249)
                .onAppear {
                    let urlString = "\(urlBase)\(self.movie.movieId).png?"
                    guard let url = URL(string: self.urlString) else { return }
                    URLSession.shared.dataTask(with: url) { (data, response, error) in
                        guard let data = data else { return }
                        guard let image = UIImage(data: data) else { return }

                        RunLoop.main.perform {
                            self.initialImage = image
                        }

                    }.resume()
                }
            } else {
                Image(uiImage: initialImage)
                .resizable()
                .cornerRadius(13.0)
                .frame(width: 135, height: 179)
                .onAppear {
                   let urlString = "\(urlBase)\(self.movie.movieId).png?"
                   guard let url = URL(string: self.urlString) else { return }
                    URLSession.shared.dataTask(with: url) { (data, response, error) in
                        guard let data = data else { return }
                        guard let image = UIImage(data: data) else { return }

                        RunLoop.main.perform {
                            self.initialImage = image
                        }

                    }.resume()
                }
            }
        }
        .onTapGesture {
            self.selectedMovie = self.movie
        }
    }
}

编辑:

我添加了以下建议,但它现在仍然可以正常工作。也许这是我添加的地方.onAppear

因此,当我启动我的应用程序时,我看到第 0 个项目被选中,但是当我点击任何项目时,视图只会重新加载,但第 0 个项目始终保持选中状态。

附加问题:

此外,我@ObservedObject var fetcher = MovieFetcher()的 inmoviesView被反复调用。

标签: iosforeachscrollviewswiftuihstack

解决方案


由于您没有提供完整的工作代码,因此我无法重现您提到的问题。但是,我建议您将 .onAppear 从 ForEach 移动到 HStack(参见下面的代码)。

我无法重现您指定的问题。

var body: some View {
    HStack(alignment: .bottom) {
        if show {
            ScrollView(.horizontal) {
                Spacer()

                HStack(alignment: .bottom, spacing: 30) {
                    ForEach(fetcher.movies, id: \.self) { item in
                        selectableRow(movie: item, selectedMovie: self.$selectMovie)
                    }
                }
                .frame(minWidth: 0, maxWidth: .infinity)
            }
            .padding(.leading, 46)
            .padding(.bottom, 26)
            .onAppear() {
                self.selectMovie = self.fetcher.movies.count > 0 ? self.fetcher.movies.first! : nil
            }
        }
    }
}

在 struct moviesView 中,使用以下代码自动选择第一部电影。

.onAppear() {
    self.selectMovie = self.movies.count > 0 ? self.movies.first! : nil
}

如果您还有其他问题,请告诉我。


推荐阅读