簡體   English   中英

SwiftUI 視圖 - viewDidLoad()?

[英]SwiftUI View - viewDidLoad()?

在視圖加載后嘗試加載圖像,驅動視圖的模型對象(參見下面的 MovieDetail)有一個 urlString。 因為 SwiftUI View元素沒有生命周期方法(並且沒有視圖控制器驅動事物)處理這個問題的最佳方法是什么?

我遇到的主要問題是無論我嘗試以哪種方式解決問題(綁定對象或使用狀態變量),我的視圖在urlString之前都沒有urlString ......

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

提前致謝。

我希望這是有幫助的。 我找到一篇博文,其中討論了在 onAppear 上為導航視圖做事。

想法是您將服務烘焙到 BindableObject 並在您的視圖中訂閱這些更新。

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 = []
                }
            }
        }
    }
}

信用:馬吉德·賈布拉伊洛夫

我們可以使用視圖修飾符來實現這一點。

  1. 創建ViewModifier
struct ViewDidLoadModifier: ViewModifier {

    @State private var didLoad = false
    private let action: (() -> Void)?

    init(perform action: (() -> Void)? = nil) {
        self.action = action
    }

    func body(content: Content) -> some View {
        content.onAppear {
            if didLoad == false {
                didLoad = true
                action?()
            }
        }
    }

}
  1. 創建View擴展:
extension View {

    func onLoad(perform action: (() -> Void)? = nil) -> some View {
        modifier(ViewDidLoadModifier(perform: action))
    }

}
  1. 像這樣使用:
struct SomeView: View {
    var body: some View {
        VStack {
            Text("HELLO!")
        }.onLoad {
            print("onLoad")
        }
    }
}

為 Xcode 11.2、Swift 5.0 全面更新

我認為viewDidLoad()正好等於在主體閉包中實現。
SwiftUI 以onAppear()onDisappear()的形式為我們提供了 UIKit 的viewDidAppear()viewDidDisappear()等價物。 您可以將任何代碼附加到您想要的這兩個事件上,SwiftUI 會在它們發生時執行它們。

例如,這將創建兩個使用onAppear()onDisappear()打印消息的視圖,並使用導航鏈接在兩者之間移動:

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView()) {
                    Text("Hello World")
                }
            }
        }.onAppear {
            print("ContentView appeared!")
        }.onDisappear {
            print("ContentView disappeared!")
        }
    }
}

參考: https : //www.hackingwithswift.com/quick-start/swiftui/how-to-respond-to-view-lifecycle-events-onappear-and-ondisappear

我正在使用init()代替。 我認為onApear()不是viewDidLoad()的替代品。 因為 onApear 在您的視圖出現時被調用。 由於您的視圖可以多次出現,因此它與調用一次的viewDidLoad沖突。

想象一下有一個TabView 通過在頁面上滑動,onApear() 被多次調用。 然而 viewDidLoad() 只被調用一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM