How to set multiple EnvironmentObjects which are same type

谁说我不能喝 提交于 2020-07-30 05:38:30

问题


I found this question SwiftUI: Putting multiple BindableObjects into Envionment

the answer said environmentObject(ObservableObject) returns modified view, therefore I can make call chain for multiple environmentObject.

like

let rootView = ContentView()
     .environmentObject(firstBindable)
     .environmentObject(secondBindable)

and I wonder what is result if firstBindable and secondBindable are same type. how .environmentObject() knows what is exect value which is a programmer intended to set between firstBindable and secondBindable.

so I tested this

  1. I made an ObservableObject class
final class TempStr: ObservableObject {
    @Published var tmpStr = "temp"

    init(initStr: String) {
        tmpStr = initStr
    }
}
  1. made call chain of environmentObject from sceneDelegate
window.rootViewController
  = UIHostingController(rootView:
      TestView()
        .environmentObject(TempStr(initStr: "1st")) 
        .environmentObject(TempStr(initStr: "2nd"))
  1. and used values from View
struct TestView: View {
  @EnvironmentObject var tmp1: TempStr
  @EnvironmentObject var tmp2: TempStr

   var body: some View {
      Text(tmp1.tmpStr + " " + tmp2.tmpStr)
   }
}
  1. result was '1st 1st'

And if my code calls one .environmentObject() like

TestView().environmentObject(TempStr(initStr: "1st")) 

both tmp1 and tmp2 from TestView have same value TempStr(initStr: "1st"). it looks like .environmentObject() call sets all values of same type.


Actually, I knew that it couldn't work but I just tried it for using this question.

I wonder what is correct way of achieving my goal.

Thanks


回答1:


This works:

SceneDelegate:

class MyModel: ObservableObject {
    @Published var tmpStr1:TempStr!
    @Published var tmpStr2:TempStr!

    init(initStr1: String, initStr2:String) {
        tmpStr1 = TempStr(initStr: initStr1)
        tmpStr2 = TempStr(initStr: initStr2)
    }
}
class TempStr: ObservableObject {
    @Published var tmpStr:String!

    init(initStr: String) {
        tmpStr = initStr
    }
}

ContentView:

struct ContentView: View {
    @EnvironmentObject var myModel: MyModel
    var body: some View {
        Text(myModel.tmpStr1.tmpStr + " " + myModel.tmpStr2.tmpStr)
    }
}

Granted, this may not be what you are looking for, but that begs the question - why do want want two instances of a class without wanting each in your model? You can easily have two separate classes as pat of your model (and as ObservableObjects) and if you want two separate instances of your model per SceneDelegate? There it is.

But if you want two instances of your model/class/whatever, it feels like a candidate for refactoring.



来源:https://stackoverflow.com/questions/57360838/how-to-set-multiple-environmentobjects-which-are-same-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!