Bru*_*ero 5 uikit ios swift swiftui combine
我有一个带有 UIViewControllers 的 UIKit 项目,我想从我的 ViewController 中展示一个基于 SwiftUI 构建的操作表。我需要将动作表的出现和消失绑定回视图控制器,使视图控制器能够被解除(并且显示动画只发生在 viewDidAppear 上,以避免在使用时发生一些奇怪的动画行为.onAppear)。这是一个代码示例,说明我希望绑定如何工作以及它如何不按我的预期工作:
import UIKit
import SwiftUI
class ViewController: UIViewController {
let button = UIButton(type: .system)
var show = true
lazy var isShowing: Binding<Bool> = .init {
self.show
} set: { show in
// This code gets called
self.show = show
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
button.setTitle("TAP THIS BUTTON", for: .normal)
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.addTarget(self, action: #selector(tapped), for: .touchUpInside)
}
@objc private func tapped() {
let vc = UIHostingController(rootView: BindingProblemView(testBinding: isShowing))
vc.modalPresentationStyle = .overCurrentContext
present(vc, animated: false)
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [self] in
isShowing.wrappedValue.toggle()
isShowing.update()
}
}
}
struct BindingProblemView: View {
@Binding var testBinding: Bool
@State var state = "ON"
var body: some View {
ZStack {
if testBinding {
Color.red.ignoresSafeArea().padding(0)
} else {
Color.green.ignoresSafeArea().padding(0)
}
Button("Test Binding is \(state)") {
testBinding.toggle()
}.onChange(of: testBinding, perform: { value in
// This code never gets called
state = testBinding ? "ON" : "OFF"
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
发生的情况是在我设置绑定值onChange后永远不会被调用。我只是完全滥用新的组合运算符吗?viewDidAppeartrue
您可以通过 s 传递数据ObservableObject,而不是使用Bindings。这里的想法是ViewController引用一个PassedData实例,该实例被传递到 SwiftUI 视图,该视图接收对象的更改,因为它是一个@ObservedObject.
现在可以使用了,因此您可以单击原始按钮来显示 SwiftUI 视图。然后,该视图中的按钮会切换passedData.isShowing以更改背景颜色。由于这是一个类实例,因此ViewController也可以访问该值。例如,isShowing也在 5 秒后切换以显示可以从或tapped()更改值。ViewController BindingProblemView
尽管不再需要它,但onChange(of:perform:)仍然会触发。
代码:
class PassedData: ObservableObject {
@Published var isShowing = true
}
Run Code Online (Sandbox Code Playgroud)
class ViewController: UIViewController {
let button = UIButton(type: .system)
let passedData = PassedData()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
button.setTitle("TAP THIS BUTTON", for: .normal)
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.addTarget(self, action: #selector(tapped), for: .touchUpInside)
}
@objc private func tapped() {
let newView = BindingProblemView(passedData: passedData)
let vc = UIHostingController(rootView: newView)
vc.modalPresentationStyle = .overCurrentContext
present(vc, animated: false)
// Example of toggling from in view controller
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.passedData.isShowing.toggle()
}
}
}
Run Code Online (Sandbox Code Playgroud)
struct BindingProblemView: View {
@ObservedObject var passedData: PassedData
var body: some View {
ZStack {
if passedData.isShowing {
Color.red.ignoresSafeArea().padding(0)
} else {
Color.green.ignoresSafeArea().padding(0)
}
Button("Test Binding is \(passedData.isShowing ? "ON" : "OFF")") {
passedData.isShowing.toggle()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |