【问题标题】:Why can't swiftui distinguish 2 different environment objects?为什么swiftui不能区分2个不同的环境对象?
【发布时间】:2020-05-14 18:14:40
【问题描述】:

我有这段代码,并且希望将 b 作为文本。

结果:a a -> 见截图。我做错了什么?

import SwiftUI

class PublishString : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

struct ContentView: View {

    @EnvironmentObject var text1 : PublishString
    @EnvironmentObject var text2 : PublishString

    var body: some View {
        VStack {
            Text(text1.string)
            Text(text2.string)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(PublishString(string: "a"))
        .environmentObject(PublishString(string: "b"))
    }
}

而且...这行得通:

class PublishString : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

class PublishString2 : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

struct ContentView: View {

    @EnvironmentObject var text1 : PublishString
    @EnvironmentObject var text2 : PublishString2

    var body: some View {
        VStack {
            Text(text1.string)
            Text(text2.string)
        }
    }
}

【问题讨论】:

  • 因为内部存储按类型区分...其实你自己发现了。

标签: swiftui


【解决方案1】:

正如Asperi 在评论中所指出的,SwiftUI 通过类型(您使用的类定义)来识别环境对象。它查找该类型的对象并使用它找到的第一个对象。

一种选择是在您可以访问的一个对象上拥有多个属性(在您的情况下,这意味着两个单独的 String 属性。

更多信息请访问 Apple documentation

【讨论】:

  • 如果我想重用一个使用这个类作为环境对象的组件?那么我不能使用多个实例吗?
  • @Chris 是的,尽管可以将不同的实例注入到祖先视图中以用于应用程序的不同部分。据我所知,这是可以的(前提是没有视图具有同一类的两个“上游”环境对象。
  • @Chris 我找到了这个答案,它提供了一种这样的方法,使用单个对象的两个属性:stackoverflow.com/a/57366566/8289095
【解决方案2】:

接受的答案完全正确,并且回答了问题。

以下是一个简单的解决方法,如果您必须使用两个相同类型的 EnvironmentObjects 在您的应用程序中传递,并且偶然发现了这个问题:

您可以创建第二个类来继承第一个类的所有内容。因此,您可以避免冗余,并且可以分别使用这两个 EnvironmentObject。

class PublishString : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

class PublishString2 : PublishString {}

struct ContentView: View {

    @EnvironmentObject var text1 : PublishString
    @EnvironmentObject var text2 : PublishString2

    var body: some View {
        VStack {
            Text(text1.string)
            Text(text2.string)
        }
    }
}

实例化:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(PublishString(string: "a"))
        .environmentObject(PublishString2(string: "b"))
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    • 2021-11-13
    • 2013-01-25
    相关资源
    最近更新 更多