简体   繁体   中英

Have 0th item in SwiftUI auto selected

I have data loaded into an HStack that is in a Scroll View in SwiftUI . Right now I have it coded where a user can tap on one of those items and have it selected. I'd like for the 0th item to already be selected upon load.

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

EDIT:

I've added the below suggestion but it's still now working properly. Maybe it's where I added the .onAppear ?

So when I launch my app I see the 0th item is selected but when I tap on any item the view just reloads but the 0th item always stays selected.

Additional issue:

Also, my @ObservedObject var fetcher = MovieFetcher() in moviesView is called repeatedly.

Since you haven't given the full working code, I wasn't able to reproduce the issue you've mentioned. However, I'd suggest you move the .onAppear from ForEach to the HStack (see code below).

I couldn't reproduce the issue you specified.

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

In the struct moviesView, use the below code to auto select the first movie.

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

Let me know if you have any other questions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM