Ios 将数据从SwiftUI传递到UIKit
我是SwiftUI新手,我一直在尝试如何在同一个应用程序中集成SwiftUI和UIKit。我用SwiftUI做了一个简单的登录屏幕Ios 将数据从SwiftUI传递到UIKit,ios,swift,swiftui,observableobject,Ios,Swift,Swiftui,Observableobject,我是SwiftUI新手,我一直在尝试如何在同一个应用程序中集成SwiftUI和UIKit。我用SwiftUI做了一个简单的登录屏幕 struct LoginView: View { var body: some View { VStack { LogoView() InputView(title: "Company Code") ButtonView(title: &qu
struct LoginView: View {
var body: some View {
VStack {
LogoView()
InputView(title: "Company Code")
ButtonView(title: "Proceed")
}
}
}
我将该视图中的所有组件提取到单独的视图(LogoView、InputView、ButtonView),从而使其可重用
我通过将视图嵌入视图控制器中的UIHostingController
来显示视图
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let controller = UIHostingController(rootView: LoginView(observable: observable))
controller.view.translatesAutoresizingMaskIntoConstraints = false
addChild(controller)
view.addSubview(controller.view)
controller.didMove(toParent: self)
NSLayoutConstraint.activate([
controller.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
controller.view.topAnchor.constraint(equalTo: view.topAnchor),
controller.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
controller.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
我的问题是如何在InputView中输入文本,并在ButtonView中点击按钮,一直到视图控制器
在这种情况下,它使用observateObject
将数据传递回视图控制器。尽管在该示例中,整个视图位于单个SwiftUI文件中。在我的例子中,我将视图分解为单独的组件
所以我想知道,observateObject
仍然是这样做的吗?因为我的视图是子视图,所以我觉得创建多个可观察对象来将值传播到子视图链上并不理想
有没有更好的方法来实现这一点
对于这个问题,肯定没有一个绝对正确的答案。您提到的observegeobject
解决方案就是其中之一。假设您只需要单向数据流(您的示例中似乎有),我可能会尝试使用一种结构,其中只包含一个通过操作调用的简单委托函数——一种Redux式的方法:
enum AppAction {
case buttonPress(value: String)
case otherButtonPress(value: Int)
}
typealias DispatchFunction = (AppAction) -> Void
struct ContentView : View {
var dispatch : DispatchFunction = { action in
print(action)
}
var body: some View {
VStack {
SubView(dispatch: dispatch)
SubView2(dispatch: dispatch)
}
}
}
struct SubView : View {
var dispatch : DispatchFunction
var body: some View {
Button(action: { dispatch(.buttonPress(value: "Test")) }) {
Text("Press me")
}
}
}
struct SubView2 : View {
var dispatch : DispatchFunction
var body: some View {
Button(action: { dispatch(.otherButtonPress(value: 2)) }) {
Text("Press me 2")
}
}
}
class ViewController : UIViewController {
func dispatch(_ action: AppAction) {
print("Action: \(action)")
}
override func viewDidLoad() {
let controller = UIHostingController(rootView: ContentView(dispatch: self.dispatch))
//...
}
}
这样,您仍然在向所有子视图传递某些内容,但是像这样传递
DispatchFunction
是一种非常简单和轻松的依赖关系。首先,使用绑定到输入视图。对于动作,使用闭包从SwiftUI到UIKit获取动作
这里有一个可能的解决办法
class LoginViewObservable: ObservableObject {
@Published var code: String = ""
var onLoginAction: (()->Void)! //<-- Button action closure
}
struct LoginView: View {
@ObservedObject var observable: LoginViewObservable
var body: some View {
VStack {
LogoView()
InputView(title: "Company Code", text: $observable.code) //<- Binding text
ButtonView(title: "Proceed", action: observable.onLoginAction) //<- Pass action
}
}
}
struct InputView: View {
let title: String
@Binding var text: String //<- Binding
var body: some View {
VStack(alignment: .leading) {
Text(title)
.foregroundColor(.gray)
.fontWeight(.medium)
.font(.system(size: 18))
TextField("", text: $text)
.frame(height: 54)
.textFieldStyle(PlainTextFieldStyle())
.padding([.leading, .trailing], 10)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray))
}
.padding()
}
}
struct ButtonView: View {
let title: String
var action: () -> Void
var body: some View {
Button(title) {
action() //<- Send action
}
.frame(minWidth: 100, idealWidth: 100, maxWidth: .infinity, minHeight: 60, idealHeight: 60)
.font(.system(size: 24, weight: .bold))
.foregroundColor(.white)
.background(Color(hex: "4980F3"))
.cornerRadius(10)
.padding([.leading, .trailing])
}
}
非常感谢。这正是我想要的。我需要更多地了解状态和绑定之间的差异。快速跟进。看起来我的LoginView SwiftUI预览无法渲染。罪魁祸首似乎是这一行
按钮视图(标题:“继续”,动作:observable.onProceedAction)
。奇怪的是,按钮的预览效果很好。你知道为什么吗?用这个按钮查看预览<代码>按钮视图(标题:“标题”,操作:{})
将此用于InputView\u预览:InputView(标题:“标题”,文本:。常量(“”)
是的,这也是我正在做的。子视图预览显示时不会出现问题。对于LoginView预览,此错误仍然存在,其中所有子视图都放在一起。奇怪的那一定是一个Xcode错误。
class LoginViewObservable: ObservableObject {
@Published var code: String = ""
var onLoginAction: (()->Void)! //<-- Button action closure
}
struct LoginView: View {
@ObservedObject var observable: LoginViewObservable
var body: some View {
VStack {
LogoView()
InputView(title: "Company Code", text: $observable.code) //<- Binding text
ButtonView(title: "Proceed", action: observable.onLoginAction) //<- Pass action
}
}
}
struct InputView: View {
let title: String
@Binding var text: String //<- Binding
var body: some View {
VStack(alignment: .leading) {
Text(title)
.foregroundColor(.gray)
.fontWeight(.medium)
.font(.system(size: 18))
TextField("", text: $text)
.frame(height: 54)
.textFieldStyle(PlainTextFieldStyle())
.padding([.leading, .trailing], 10)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray))
}
.padding()
}
}
struct ButtonView: View {
let title: String
var action: () -> Void
var body: some View {
Button(title) {
action() //<- Send action
}
.frame(minWidth: 100, idealWidth: 100, maxWidth: .infinity, minHeight: 60, idealHeight: 60)
.font(.system(size: 24, weight: .bold))
.foregroundColor(.white)
.background(Color(hex: "4980F3"))
.cornerRadius(10)
.padding([.leading, .trailing])
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Other code----
observable.onLoginAction = { [weak self] in //<-- Get login action
print(self?.observable.code ?? "")
}
}