SwiftUI 通过引用将 class 对象传递给另一个视图
SwiftUI pass by reference a class object to another view
我正在尝试学习 SwiftUI,我打算开发一个带有选项卡视图并在这些视图之间共享核心运动数据的简单应用。
主要思想是创建一个运动管理器对象(如 )并在所有视图中使用传感器值。
ContentView.swift
:
import SwiftUI
struct ContentView: View {
@State private var selection = 1
@State private var viewNames : [String] = ["View1", "View2"]
var body: some View {
TabView(selection: $selection){
View1(viewName: $viewNames[0]).tag(0)
View2(viewName: $viewNames[1]).tag(1)
}
}
}
View1.swift
:
import SwiftUI
struct View1 : View {
@Binding var viewName : String
var body: some View {
Text("First View")
.font(.title)
.foregroundColor(Color.gray)
.tabItem {
VStack {
Image(systemName: "star")
Text(viewName)
}
}
}
}
View2.swift
:
struct View2 : View {
@Binding var viewName : String
var body: some View {
VStack {
Text("Second View")
.font(.title)
.foregroundColor(Color.green)
.padding(.top)
View21(motionManager: MotionManager())
}.tabItem {
VStack {
Image(systemName:"heart")
Text(viewName)
}
}
}
}
View21.swift
struct View21 : View {
@ObservedObject var motionManager : MotionManager
@State private var showDetails = false
var body: some View{
Text(String(format: "%.2f", motionManager.x))
}
使用这些代码,我可以在 View21
中使用传感器数据,但我无法访问上面层次结构中的视图中的数据。
此外,我在 ContentView 中创建了 @ObservedObject
(如 here)并将其传递给所有视图。我的应用程序可以在模拟器中运行,但不能在真实设备上运行。
我可以看到传感器数据发生变化,但无法切换选项卡视图。
我尝试使用 @EnvironementObject
而不是 @ObservedObject
,但行为是一样的。
我将非常感谢您对我的问题的任何帮助和提示。
祝福
好的,所以 Paulw11 是正确的,您可能想将 ObservableObject 注入到您的环境中,然后在每个想要访问该实例的视图中,您只需添加一个 属性 和 @EnvironmentObject 属性包装纸。下面我把我能想到的最简单的例子放在一起,这样你就可以了解它是如何工作的。
import SwiftUI
import Combine
class ManagerPlaceholder: ObservableObject {
@Published var propertyOne: Double = 1.0
@Published var propertyTwo: Double = 2.0
func action() {
propertyOne = Double.random(in: 0.0..<100.00)
propertyTwo = Double.random(in: 0.0..<100.00)
}
}
struct ContentView: View {
@EnvironmentObject var manager: ManagerPlaceholder
var body: some View {
TabView {
Subview()
.tabItem { Label("First", systemImage: "hexagon.fill") }
.tag(1)
Subview()
.tabItem { Label("Second", systemImage: "circle.fill") }
.tag(2)
}
}
}
struct Subview: View {
@EnvironmentObject var manager: ManagerPlaceholder
var body: some View {
VStack {
Text("Prop One: \(manager.propertyOne)").padding()
Text("Prop Two: \(manager.propertyTwo)").padding()
Button("Change", action: manager.action).padding()
}
}
}
以上就是
- 一个简单的 ObservableObject - 它所做的只是设置两个具有随机值的双精度值(注意您要观察的属性被标记为@Published)
- 选项卡视图
- 一个简单的sub-view
请注意,两个视图都有 @EnvironmentObject var manager: ManagerPlaceholder
。您不直接设置 属性 。该行表示您要引用环境中的 ManagerPlaceholder 实例。环境是 SwiftUI 为您管理的一种存储“池”。您可以向它添加一个对象的实例,然后在 sub-view 需要它的地方引用它。
因此,为确保在实例化视图(可以是选项卡视图或任何 super-view)时将其添加到环境中。因此,例如在您的 _NAME_App.swift(对于 iOS 14 目标)或 SceneDelegate.swift(对于 iOS 13 目标)中,您将像这样实例化您的视图:
ContentView().environmentObject(ManagerPlaceholder())
如果您运行上面的代码,当您点击“更改”按钮时,您会看到它随机设置了两个属性,并且当您来回切换时,两个子视图将看到完全相同的值,因为它们都在引用同一个实例。
如有任何不清楚的地方,请随时发表评论。
我正在尝试学习 SwiftUI,我打算开发一个带有选项卡视图并在这些视图之间共享核心运动数据的简单应用。
主要思想是创建一个运动管理器对象(如
ContentView.swift
:
import SwiftUI
struct ContentView: View {
@State private var selection = 1
@State private var viewNames : [String] = ["View1", "View2"]
var body: some View {
TabView(selection: $selection){
View1(viewName: $viewNames[0]).tag(0)
View2(viewName: $viewNames[1]).tag(1)
}
}
}
View1.swift
:
import SwiftUI
struct View1 : View {
@Binding var viewName : String
var body: some View {
Text("First View")
.font(.title)
.foregroundColor(Color.gray)
.tabItem {
VStack {
Image(systemName: "star")
Text(viewName)
}
}
}
}
View2.swift
:
struct View2 : View {
@Binding var viewName : String
var body: some View {
VStack {
Text("Second View")
.font(.title)
.foregroundColor(Color.green)
.padding(.top)
View21(motionManager: MotionManager())
}.tabItem {
VStack {
Image(systemName:"heart")
Text(viewName)
}
}
}
}
View21.swift
struct View21 : View {
@ObservedObject var motionManager : MotionManager
@State private var showDetails = false
var body: some View{
Text(String(format: "%.2f", motionManager.x))
}
使用这些代码,我可以在 View21
中使用传感器数据,但我无法访问上面层次结构中的视图中的数据。
此外,我在 ContentView 中创建了 @ObservedObject
(如 here)并将其传递给所有视图。我的应用程序可以在模拟器中运行,但不能在真实设备上运行。
我可以看到传感器数据发生变化,但无法切换选项卡视图。
我尝试使用 @EnvironementObject
而不是 @ObservedObject
,但行为是一样的。
我将非常感谢您对我的问题的任何帮助和提示。 祝福
好的,所以 Paulw11 是正确的,您可能想将 ObservableObject 注入到您的环境中,然后在每个想要访问该实例的视图中,您只需添加一个 属性 和 @EnvironmentObject 属性包装纸。下面我把我能想到的最简单的例子放在一起,这样你就可以了解它是如何工作的。
import SwiftUI
import Combine
class ManagerPlaceholder: ObservableObject {
@Published var propertyOne: Double = 1.0
@Published var propertyTwo: Double = 2.0
func action() {
propertyOne = Double.random(in: 0.0..<100.00)
propertyTwo = Double.random(in: 0.0..<100.00)
}
}
struct ContentView: View {
@EnvironmentObject var manager: ManagerPlaceholder
var body: some View {
TabView {
Subview()
.tabItem { Label("First", systemImage: "hexagon.fill") }
.tag(1)
Subview()
.tabItem { Label("Second", systemImage: "circle.fill") }
.tag(2)
}
}
}
struct Subview: View {
@EnvironmentObject var manager: ManagerPlaceholder
var body: some View {
VStack {
Text("Prop One: \(manager.propertyOne)").padding()
Text("Prop Two: \(manager.propertyTwo)").padding()
Button("Change", action: manager.action).padding()
}
}
}
以上就是
- 一个简单的 ObservableObject - 它所做的只是设置两个具有随机值的双精度值(注意您要观察的属性被标记为@Published)
- 选项卡视图
- 一个简单的sub-view
请注意,两个视图都有 @EnvironmentObject var manager: ManagerPlaceholder
。您不直接设置 属性 。该行表示您要引用环境中的 ManagerPlaceholder 实例。环境是 SwiftUI 为您管理的一种存储“池”。您可以向它添加一个对象的实例,然后在 sub-view 需要它的地方引用它。
因此,为确保在实例化视图(可以是选项卡视图或任何 super-view)时将其添加到环境中。因此,例如在您的 _NAME_App.swift(对于 iOS 14 目标)或 SceneDelegate.swift(对于 iOS 13 目标)中,您将像这样实例化您的视图:
ContentView().environmentObject(ManagerPlaceholder())
如果您运行上面的代码,当您点击“更改”按钮时,您会看到它随机设置了两个属性,并且当您来回切换时,两个子视图将看到完全相同的值,因为它们都在引用同一个实例。
如有任何不清楚的地方,请随时发表评论。