【问题标题】:What does the attribute `@EnvironmentObject` mean in the SwiftUI?SwiftUI 中的 `@EnvironmentObject` 属性是什么意思?
【发布时间】:2020-09-11 09:25:32
【问题描述】:

正如您在official tutorial project 中看到的,在var 之前有一个奇怪的@EnvironmentObject。什么意思?

struct LandmarkDetail: View {
    @EnvironmentObject var userData: UserData
    var landmark: Landmark

    var landmarkIndex: Int {
        userData.landmarks.firstIndex(where: { $0.id == landmark.id })!
    }
    // ...
}

【问题讨论】:

标签: ios swift swiftui


【解决方案1】:

例如,出于网络目的。你有一个符合BindableObject(Beta 5:ObservableObject)的类,并通过PassthroughSubject(Beta 5:@Published)发送你的数据。

例如这种情况:

SwiftUI (1.0)

struct Course: Decodable {
    let name: String
}

class NetworkManager: ObservableObject {

    @Published var courses = [Course]()

    func getAllCourses() {
        guard let url = URL(string: "https://api.letsbuildthatapp.com/jsondecodable/courses") else { return }
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            do {
                let courses = try JSONDecoder().decode([Course].self, from: data!)
                DispatchQueue.main.async {
                    self.courses = courses
                }
            } catch {
                print("Failed To decode: ", error)
            }
        }.resume() // VERY IMPORTANT! As the request won't run
    }
}

struct ContentView : View {
    @ObservedObject var networkManager: NetworkManager = NetworkManager()
    // Or this
    // @EnvironmentObject var networkManager: NetworkManager // Don't forget to instaniate it with .environmentObject()

    var body: some View {
        VStack {
            Button(action: {
                self.networkManager.getAllCourses()
            }, label: {
                Text("Get All Courses")
            })

            List(networkManager.courses, id: \.name) {
                Text($0.name)
            }
        }
    }
}

测试版

struct Course: Decodable {
    let name: String
}

class NetworkManager: BindableObject {
    let didChange = PassthroughSubject<NetworkManager, Never>()

    var courses = [Course]() {
        didSet {
            didChange.send(self)
        }
    }

    func getAllCourses() {
        guard let url = URL(string: "https://api.letsbuildthatapp.com/jsondecodable/courses") else { return }
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            do {
                let courses = try JSONDecoder().decode([Course].self, from: data!)
                DispatchQueue.main.async {
                    self.courses = courses
                }
            } catch {
                print("Failed To decode: ", error)
            }
        }.resume() // VERY IMPORTANT! As the request won't run
    }
}

struct ContentView : View {
    @EnvironmentObject var networkManager: NetworkManager

    var body: some View {
        VStack {
            Button(action: {
                self.networkManager.getAllCourses()
            }, label: {
                Text("Get All Courses")
            })

            List(networkManager.courses.identified(by: \.name)) {
                Text($0.name)
            }
        }
    }
}

【讨论】:

  • 我试着用你的例子玩了一下,但我有这些 Use of unresolved identifier 'PassthroughSubject'Type 'NetworkManager' does not conform to protocol 'BindableObject' 错误。
  • 你需要导入Combine a new framework by apple
  • 抱歉,我没有注意到我忘记了导入。你能告诉我更多关于 BindableObject 协议的信息吗?我很难理解它实际上做了什么......:/
  • @Que20 请接受我的回答。 @ObjectBinding 是外部引用属性。实际上,应该显示的是您的数据模型。 @EnvironmentObject - 与@ObjectBinding 相同,但它跨环境使用到其他视图,而@ObjectBinding 应显式传递
  • 非常感谢,这为我节省了很多时间。我使用 passthroughtsubject 跟踪所有旧代码,这在最新的测试版中根本不起作用。
【解决方案2】:

它旨在让您的视图自动访问模型,而无需依赖注入。

在场景委托中设置环境对象一次,然后层次结构中的所有视图都可以通过自己的魔法属性访问它。我相信视图也可以为其子对象覆盖对象,但我还没有测试过。

【讨论】:

    【解决方案3】:

    环境对象

    我从苹果文档中找到的。

    来自苹果的描述:

    一个动态视图属性,它使用由 祖先视图在可绑定时使当前视图无效 对象变化。

    apple doc

    我的理解是当我们设置一个值或对象时是 init。例如:列表。 当我们重新加载列表时,一些显示的视图对象被替换和删除。

    【讨论】:

      【解决方案4】:

      它是一个 BindableObject,SwiftUI 将使用它来确定如何通过访问该对象来刷新视图。查看示例中的 UserData 类。声明环境对象的视图的任何子视图都可以访问它。在这种情况下userData

      【讨论】:

        猜你喜欢
        • 2019-09-13
        • 1970-01-01
        • 1970-01-01
        • 2019-06-12
        • 2011-05-16
        • 2013-06-13
        • 2016-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多