阅读 166

SwiftUI实战-仿写微信App(六)

一、跨层级数据共享

前面的章节提到过,父级使用@State修饰变量,子级使用@Binding修饰变量,并通过参数的传递,可以实现变量的共享即不管是父级还是子级改变该变量的值,对方都会感知到。

共享共享父级变量子级

但是还有一种情况,就是数据在多个View中都有引用,它们并不是父子级的关系,也希望共享该变量。

共享共享View1变量View3View2.1View2.2

View1和View3都持有该变量,但是并非父子级关系。

二、Combine框架

SwiftUI提供了一个框架Combine,使用MVVM设计模式。

MVVMModel-View-ViewModel的简写。

  • Model指代共享变量。

  • View就是视图层,同上文的View1,View2,View3

  • ViewModel类似一个枢纽,把ModelView联结起来。

ViewViewModelModel

  • ViewModel持有变量Model,通过某些手段(后面会讲)将Model变成共享变量。

  • View中引入ViewModel类,通过ViewModel操作Model,比如增删改等操作,其它引用View都会得到通知。

三、ModelView

先创建一个ModelView类。Xcode创建Swift File而非SwiftUI View

image.png

import Foundation class AnimalViewModel{      } 复制代码

注意:这里ViewModel必须是class,而不是struct

然后实现ObservableObject协议,通知SwiftUI这是一个ViewModel类。

四、Model

接下来在ViewModel中创建Model

class AnimalViewModel: ObservableObject{          var animals: [String] = []      } 复制代码

Model不拘泥数据类型,不管是数组,还是其它类型均可,即使是一个Bool变量都可以。

同理Model也需要证明自己,所以使用@Publish注解修饰。

@Published var animals: [String] = [] 复制代码

五、View

View中引用ViewModel

创建两个View:TVViewPCView,分别引入ViewModel,并显示同样的List列表。

比如TVViewPCViewTVView

struct TVView: View {          var model: AnimalViewModel          var body: some View {         List{             Text("TVView")             Button(action: {                 model.animals.append("cat")             }, label: {                 Text("addAnimal")             })             ForEach(0..<model.animals.count, id: \.self){index in                 Text(model.animals[index])             }         }     } } 复制代码

同前面两步,View同样需要通知SwiftUI它对ViewModel的引用。使用@EnvironmentObject修饰ViewModel

@EnvironmentObject var model: AnimalViewModel 复制代码

六、ViewModel层级

最后,虽然使用@EnvironmentObject注解标记了ViewModel,但是没有通知SwiftUI在哪创建ViewModel,也即在哪个View层级上创建ViewModel

View1上创建ViewModelView2.1上创建ViewModelView1View2.2View3.3View3.4View3.1View2.1View3.2

如上图,

如果在View1层级创建ViewModelModel能够在View1View2View3所有层级中共享。

如果在View2.1层级创建,Model只能在View2.1View3.1View3.2中共享。

那么具体怎么创建呢?

WeChatModel项目中,ContentView作为最上级的View,只需要找到创建ContentView的位置。

如下图

image.png

看清楚,虽然都是EnvironmentObject,一个是使用@EnvironmentObject注解标记View中的ViewModel,另一个是指定ViewModel的影响范围。

我们只需要指定影响范围即可,具体什么时间创建,是由SwiftUI自己决定的。

最终效果如下:

屏幕录制2021-08-06 21.39.16.gif

附:代码地址


作者:徒手完结
链接:https://juejin.cn/post/6993312402913624094


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐