swift - 如何从另一个类更改@Binding var?
问题描述
我有一个视图,它以这种方式包含在 SwiftUI 中的另一个视图中:
第一个视图
struct CircularProgressBar: View {
@Binding var circleProgress: CGFloat
var widthAndHeight: CGFloat
var labelSize: CGFloat?
var staticColor: Color?
var progressColor: Color
var showLabel: Bool?
var lineWidth: CGFloat?
var body: some View {
GeometryReader { geometry in
ZStack {
Circle()
.stroke(self.staticColor ?? Color.gray, lineWidth: self.lineWidth ?? 15)
.frame(width: geometry.size.width, height: geometry.size.height)
Circle()
.trim(from: 0.0, to: self.circleProgress)
.stroke(self.progressColor, lineWidth: self.lineWidth ?? 15)
.frame(width: geometry.size.width, height: geometry.size.width)
.rotationEffect(Angle(degrees: -90))
if self.showLabel ?? true {
Text("\(Int(self.circleProgress*100))%")
.frame(width: geometry.size.width, height: geometry.size.height)
.font(.custom("HelveticaNeue", size: self.labelSize ?? 20.0))
}
}
}
.frame(width: widthAndHeight, height: widthAndHeight)
}
}
第二视图:
struct ContentView: View {
@ObservedObject var simulator:Simulator
@State var progress: CGFloat
var body: some View {
HStack(alignment: .center) {
VStack(alignment: .leading) {
Text(simulator.getName())
Text("Version: "+simulator.getVersion())
Spacer()
Image("logo")
.resizable()
.frame(width: 50, height: 40)
}.padding()
VStack(alignment: .center) {
Text("State")
.frame(maxWidth: .infinity, maxHeight: .infinity)
CircularProgressBar(circleProgress: $progress, widthAndHeight: 180, labelSize: 30, progressColor: .blue)
Button(action: {
withAnimation{self.updateCircleProg()}
//Action here
}) {
Text("Show Logs")
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
func updateCircleProg(){
self.progress = CGFloat(Float.random(in: 0 ..< 1))
}
}
我能够从模拟器 Object 上的另一个类更新 UI,因为它被声明为ObservableObject
并且其属性为@Published
我能够改变progress
第二视图的内部。
我的问题是:是否可以progress
从另一个类更改包含在第二视图中的第一视图并更新 UI?(超出第二个视图)?
我尝试更改它,但 UI 没有更新,这就是我所做的:
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
var simulator : Simulator!
func applicationDidFinishLaunching(_ aNotification: Notification) {
simulator = Simulator(name: "simulator", version: "1")
let contentView = ContentView(simulator: simulator, progress: 0.0)
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.simulator.setName(name: "Big Simulator")
self.simulator.setVersion(version: "2")
contentView.progress = 0.3
}
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .miniaturizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView)
window.makeKeyAndOrderFront(nil)
}
解决方案
好吧,SwiftUI 以不同的方式工作......所以你需要
class Simulator: ObservableObject {
@Published var progress: CGFloat = .zero // << and here
所以更新
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.simulator.setName(name: "Big Simulator")
self.simulator.setVersion(version: "2")
self.simulator.progress = 0.3 // << modifier here or anywhere
}
和
VStack(alignment: .center) {
Text("State")
.frame(maxWidth: .infinity, maxHeight: .infinity)
// observe here
CircularProgressBar(circleProgress: self.$simulator.progress, widthAndHeight: 180, labelSize: 30, progressColor: .blue)
注意: @State
设计为仅在内部视图中使用,因此遵循此规则很容易养成为 state 属性赋予private的习惯,始终如此。
推荐阅读
- node.js - 使用 Node JS 和 React 出错
- java - 如何编辑对话框文本
- deep-linking - 如何为我的 Android 应用添加深层链接?
- python - 导入 PyInstaller 模块并编译时出错
- python - 重新采样后调整预测概率
- python - 如何将python字符串元组转换为整数元组?
- c - struct Employee {} 比较 struct {} Employee
- java - NetworkInfo.isConnected() 和 NetworkInfo.getDetailedState() == NetworkInfo.DetailedState.CONNECTED 之间的区别。用什么?
- php - 我无法将 POST 请求从 android volley 发送到 php
- performance-testing - 为负载运行器生成报告 pdf 的命令行方式