This is the sixth day of my participation in the August More text Challenge. For details, see:August is more challenging

above

  • SwiftUI actual Combat – Copy wechat App (1)
  • SwiftUI Actual Combat – Copy wechat App (2)
  • SwiftUI Actual Combat – Copy wechat App (3)
  • SwiftUI Actual Combat – Copy wechat App (4)
  • SwiftUI Actual Combat – Copy wechat App (5)

1. Cross-layer data sharing

As mentioned in the previous chapter, the parent modifies the variable with @state, and the child modifies the variable with @binding. By passing the parameter, the variable can be shared, that is, whether the parent or the child changes the value of the variable, each other will be aware of it.

Graph LR parent - > share | | variable child - > share | | variable

However, there is also a case where data is referenced in multiple views that are not parent and want to share the variable.

Shared graph TD the View1 = = > | | variable View3 = = > share | | variable View2.1 - > View3 View2.2 - > View3 the View1 - > View2.1 the View1 - > View2.2

View1 and View3 both hold this variable, but not at the parent level.

2. Combine framework

SwiftUI provides a framework, Combine, which uses the MVVM design pattern.

MVVM is short for Model-view-ViewModel.

  • ModelThis refers to shared variables.
  • ViewThat’s the view layer, same as aboveView1,View2,View3.
  • ViewModelSimilar to a hub, putModelandViewLink it up.
graph LR
subgraph ViewModel
Model
end
subgraph View
ViewModel
end
  • ViewModelHold a variableModelBy some means (more on that later) willModelBecomes a shared variable.
  • ViewThe introduction ofViewModelClass,ViewModeloperationModel, such as adding, deleting, and other operations, other referencesViewWill be notified.

Three, the ModelView

Start by creating a ModelView class. Xcode creates a Swift File instead of a SwiftUI View

import Foundation

class AnimalViewModel{}Copy the code

Note: The ViewModel must be a class, not a struct.

Then implement the ObservableObject protocol, informing SwiftUI that this is a ViewModel class.

Fourth, the Model

Next, create the Model in ViewModel.

class AnimalViewModel: ObservableObject{
    
    var animals: [String] =[]}Copy the code

Model is not a data type. It can be an array or any other type, even if it is a Bool variable.

Similarly, the Model needs to prove itself, so use the @publish annotation.

@Published var animals: [String] = []
Copy the code

Fifth, the View

Reference the ViewModel in the View.

Create two views :TVView and PCView, import ViewModel respectively, and display the same List.

Like TVView, PCView is the same as TVView.

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])
            }
        }
    }
}
Copy the code

As in the previous two steps, the View also needs to notify SwiftUI of its reference to the ViewModel. Modify the ViewModel with @environmentobject.

@EnvironmentObject var model: AnimalViewModel
Copy the code

Vi.ViewModelThe hierarchy

Finally, while the ViewModel is tagged with the @Environmentobject annotation, SwiftUI is not informed where to create the ViewModel, that is, on what View hierarchy to create the ViewModel on.

Graph TD subgraph View1 create ViewModel View1 --> View2.1 View1 --> View2.2 View2.1 --> View3.2 end View2.2 --> View3.3 --> View3.4 end

As shown above,

If you create a ViewModel at the View1 level, the Model can be shared across all levels View1, View2, and View3.

If created at the View2.1 level, the Model can only be shared in View2.1, View3.1, and View3.2.

So how do you create that?

In the WeChatModel project, the ContentView is the top View. You just need to find where the ContentView was created.

The following figure

To be clear, although both are EnvironmentObject, one uses the @environmentobject annotation to tag the ViewModel in the View and the other specifies the scope of influence of the ViewModel.

All we need to do is specify the scope of influence, and it’s up to SwiftUI to decide when to create it.

The final result is as follows:

Attached: Code address

Gitee.com/dkwingcn/we…