ios SwiftUI视图-视图DidLoad()?

wmomyfyw  于 2022-12-20  发布在  iOS
关注(0)|答案(4)|浏览(274)

试图在视图加载后加载图像时,驱动视图的模型对象(参见下面的MovieDetail)有一个urlString。由于SwiftUI View元素没有生命周期方法(并且没有视图控制器驱动事物),处理这个问题的最佳方法是什么?
我遇到的主要问题是,无论我尝试用哪种方法来解决问题(绑定对象或使用State变量),我的视图在加载之前都没有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)
            }
        }
    }
}
wpx232ag

wpx232ag1#

我们可以使用视图修改器来实现这一点。
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")
        }
    }
}
1yjd4xko

1yjd4xko2#

我希望这对你有帮助。我找到了a blogpost,它谈到了在导航视图中做一些事情。
我们的想法是将服务烘焙到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 = []
                }
            }
        }
    }
}

贷方:Majid Jabrayilov

ldxq2e6h

ldxq2e6h3#

针对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

jv4diomz

jv4diomz4#

我用init()代替。我认为onApear()不是viewDidLoad()的替代品。因为onApear在你的视图出现时被调用。因为你的视图可以出现多次,它与viewDidLoad冲突,viewDidLoad只被调用一次。
假设有一个TabView,通过在页面上滑动,Apear()被调用了多次,而viewDidLoad()只被调用了一次。

相关问题