Имейте 0-ый пункт в SwiftUI, автоматически выбранный - PullRequest
2 голосов
/ 13 марта 2020

У меня есть данные, загруженные в HStack, который находится в Scroll View в SwiftUI. Прямо сейчас у меня есть код, где пользователь может нажать на один из этих элементов и выбрать его. Я бы хотел, чтобы 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() в moviesView вызывается повторно.

1 Ответ

1 голос
/ 13 марта 2020

Поскольку вы не дали полный рабочий код, я не смог воспроизвести проблему, о которой вы упоминали. Однако я бы посоветовал вам переместить .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 используйте приведенный ниже код для автоматического выбора первого mov ie.

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

Дайте мне знать, если у вас есть какие-либо другие вопросы.

...