SwiftUI中如何在子视图内调用主视图方法刷新列表
SwiftUI子视图调用主视图逻辑的三种实现方案
下面针对你的场景提供三种常用的落地实现,你可以根据自己的项目复杂度选择:
方案1:闭包回调(最推荐,低耦合)
这个方案的优势是子视图完全不需要感知父视图的实现细节,仅通过回调触发操作,耦合度最低,适合你当前单层父子视图的场景。
- 修改子视图
MovieView,新增回调属性:
struct MovieView: View { let movie: Movie // 新增回调属性,用于通知父视图执行操作 var onHide: () -> Void var body: some View { VStack(alignment: .leading) { HStack { Text("Movie Title: \(movie.title)") }.padding([.top, .leading, .bottom]) Button("Do not show this movie") { // 先执行存储用户隐藏偏好的自有逻辑 // 触发回调通知父视图执行刷新 self.onHide() } } } }
- 修改主视图初始化子视图的逻辑,传入要执行的主视图操作:
ForEach(self.viewModel.movie) { movie in MovieView(movie: movie) { // 这里写主视图需要执行的逻辑 self.viewModel.fetchMovies() } }
方案2:直接传递ViewModel
适合业务逻辑都封装在ViewModel中的场景,不需要额外维护回调参数。
- 修改子视图,新增ViewModel属性:
struct MovieView: View { let movie: Movie @ObservedObject var viewModel: MovieViewModel var body: some View { VStack(alignment: .leading) { HStack { Text("Movie Title: \(movie.title)") }.padding([.top, .leading, .bottom]) Button("Do not show this movie") { // 存储用户隐藏偏好的逻辑 // 直接调用ViewModel的刷新方法 self.viewModel.fetchMovies() } } } }
- 主视图初始化子视图时传入自身持有的ViewModel实例:
ForEach(self.viewModel.movie) { movie in MovieView(movie: movie, viewModel: self.viewModel) }
方案3:使用EnvironmentObject注入(适合视图层级深的场景)
如果你的子视图嵌套层级超过2层,一层一层传递参数非常麻烦,可以用环境对象全局共享ViewModel实例。
- 主视图根位置注入ViewModel到环境:
struct MovieList: View { @ObservedObject var viewModel = MovieViewModel() var body: some View { VStack { ScrollView(.vertical) { VStack { ForEach(self.viewModel.movie) { movie in MovieView(movie: movie) } } } } .navigationBarTitle("Movies") .onAppear { self.viewModel.fetchMovies() } // 注入到环境中,所有子子孙视图都可以直接获取该实例 .environmentObject(viewModel) } }
- 子视图直接从环境中读取ViewModel:
struct MovieView: View { let movie: Movie // 从环境中自动获取ViewModel,不需要手动传递 @EnvironmentObject var viewModel: MovieViewModel var body: some View { VStack(alignment: .leading) { HStack { Text("Movie Title: \(movie.title)") }.padding([.top, .leading, .bottom]) Button("Do not show this movie") { // 存储用户隐藏偏好的逻辑 self.viewModel.fetchMovies() } } } }
注意:使用EnvironmentObject时需要确保上层父视图已经完成注入,否则应用运行时会抛出崩溃错误。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

