SwiftUI 中的“@EnvironmentObject”属性是什么意思?
What does the attribute `@EnvironmentObject` mean in the SwiftUI?
正如您在 official tutorial project 中看到的,var
之前有一个奇怪的 @EnvironmentObject
。这是什么意思?
struct LandmarkDetail: View {
@EnvironmentObject var userData: UserData
var landmark: Landmark
var landmarkIndex: Int {
userData.landmarks.firstIndex(where: { [=10=].id == landmark.id })!
}
// ...
}
环境对象
我从苹果文档中找到了。
Description from apple:
A dynamic view property that uses a bindable object supplied by an
ancestor view to invalidate the current view whenever the bindable
object changes.
我的理解是当我们设置一个值或对象时被初始化。例如:列表。
当我们重新加载一个列表时,一些显示的视图对象被替换和删除。
它是一个 BindableObject,SwiftUI 将使用它来确定如何通过访问该对象来刷新您的视图。查看示例中的 UserData class。声明环境对象的视图的任何子级都可以访问它。在这种情况下 userData
.
例如,这是出于网络目的。您有一个 class 符合 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([=10=].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([=11=].name)
}
}
}
}
它旨在让您的视图自动访问模型,而无需依赖项注入。
在场景委托中设置一次环境对象,然后层次结构中的所有视图都可以通过自己的魔法访问它 属性。我相信视图也可以为其子对象覆盖对象,但我还没有测试过。
正如您在 official tutorial project 中看到的,var
之前有一个奇怪的 @EnvironmentObject
。这是什么意思?
struct LandmarkDetail: View {
@EnvironmentObject var userData: UserData
var landmark: Landmark
var landmarkIndex: Int {
userData.landmarks.firstIndex(where: { [=10=].id == landmark.id })!
}
// ...
}
环境对象
我从苹果文档中找到了。
Description from apple:
A dynamic view property that uses a bindable object supplied by an ancestor view to invalidate the current view whenever the bindable object changes.
我的理解是当我们设置一个值或对象时被初始化。例如:列表。 当我们重新加载一个列表时,一些显示的视图对象被替换和删除。
它是一个 BindableObject,SwiftUI 将使用它来确定如何通过访问该对象来刷新您的视图。查看示例中的 UserData class。声明环境对象的视图的任何子级都可以访问它。在这种情况下 userData
.
例如,这是出于网络目的。您有一个 class 符合 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([=10=].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([=11=].name)
}
}
}
}
它旨在让您的视图自动访问模型,而无需依赖项注入。
在场景委托中设置一次环境对象,然后层次结构中的所有视图都可以通过自己的魔法访问它 属性。我相信视图也可以为其子对象覆盖对象,但我还没有测试过。