Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI View - viewDidLoad()?

Trying to load an image after the view loads, the model object driving the view (see MovieDetail below) has a urlString. Because a SwiftUI View element has no life cycle methods (and there's not a view controller driving things) what is the best way to handle this?

The main issue I'm having is no matter which way I try to solve the problem (Binding an object or using a State variable), my View doesn't have the urlString until after it loads...

// movie object struct Movie: Decodable, Identifiable {      let id: String     let title: String     let year: String     let type: String     var posterUrl: String      private enum CodingKeys: String, CodingKey {         case id = "imdbID"         case title = "Title"         case year = "Year"         case type = "Type"         case posterUrl = "Poster"     } } 
// root content list view that navigates to the detail view struct ContentView : View {      var movies: [Movie]      var body: some View {         NavigationView {             List(movies) { movie in                 NavigationButton(destination: MovieDetail(movie: movie)) {                     MovieRow(movie: movie)                 }             }             .navigationBarTitle(Text("Star Wars Movies"))         }     } } 
// detail view that needs to make the asynchronous call struct MovieDetail : View {      let movie: Movie     @State var imageObject = BoundImageObject()      var body: some View {         HStack(alignment: .top) {             VStack {                 Image(uiImage: imageObject.image)                     .scaledToFit()                  Text(movie.title)                     .font(.subheadline)             }         }     } } 

Thanks in advance.

like image 771
Kraig Wastlund Avatar asked Jun 07 '19 14:06

Kraig Wastlund


People also ask

Is there a viewDidLoad in SwiftUI?

SwiftUI gives us equivalents to UIKit's viewDidAppear() and viewDidDisappear() in the form of onAppear() and onDisappear() . You can attach any code to these two events that you want, and SwiftUI will execute them when they occur.

What is viewDidLoad in Swift?

viewDidLoad is called when the ViewController has loaded its view hierarchy into memory. This is the point where you can perform your customized initialisation for your view controller. For instance, if your view controller has a UILabel and you want to set a custom text to it, this is the point where you do that.

How do Views work in SwiftUI?

SwiftUI builds the view hierarchy of a View by calling the body property to initialise its children. It will then call the body property of each of those children, which may then initialise their own children, which have their body property called, and so on.


1 Answers

I hope this is helpful. I found a blogpost that talks about doing stuff onAppear for a navigation view.

Idea would be that you bake your service into a BindableObject and subscribe to those updates in your view.

struct SearchView : View {     @State private var query: String = "Swift"     @EnvironmentObject var repoStore: ReposStore      var body: some View {         NavigationView {             List {                 TextField($query, placeholder: Text("type something..."), onCommit: fetch)                 ForEach(repoStore.repos) { repo in                     RepoRow(repo: repo)                 }             }.navigationBarTitle(Text("Search"))         }.onAppear(perform: fetch)     }      private func fetch() {         repoStore.fetch(matching: query)     } } 
import SwiftUI import Combine  class ReposStore: BindableObject {     var repos: [Repo] = [] {         didSet {             didChange.send(self)         }     }      var didChange = PassthroughSubject<ReposStore, Never>()      let service: GithubService     init(service: GithubService) {         self.service = service     }      func fetch(matching query: String) {         service.search(matching: query) { [weak self] result in             DispatchQueue.main.async {                 switch result {                 case .success(let repos): self?.repos = repos                 case .failure: self?.repos = []                 }             }         }     } } 

Credit to: Majid Jabrayilov

like image 76
andromedainiative Avatar answered Sep 22 '22 01:09

andromedainiative