在主体外访问 SwiftUI 视图中的状态变量
Posted
技术标签:
【中文标题】在主体外访问 SwiftUI 视图中的状态变量【英文标题】:Accessing state variable in SwiftUI View outside the body 【发布时间】:2019-09-05 15:35:32 【问题描述】:我有一个内容视图,我想动态跟踪高度。
我已经实现了这个解决方案,但我遇到了这个异常:
致命错误:访问 View.body 外部的状态:文件
我该怎么做才能让键盘高度动态更新我的 UI
struct ContentView: View
@State var keyboardHeight: CGFloat = 0
var cancellables: Set<AnyCancellable> = []
init()
NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification)
.merge(with: NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification))
.compactMap( notification in
guard let keyboardFrameValue: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else return nil
let keyboardFrame = keyboardFrameValue.cgRectValue
if keyboardFrame.origin.y == UIScreen.main.bounds.height
return 0
else
return keyboardFrame.height - (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0)
)
.assign(to: \.keyboardHeight, on: self)
.store(in: &cancellables)
var body: some View
VStack
ZStack(alignment: Alignment.bottom)
List
Text("Default text").foregroundColor(Color.red)
TextField("Placeholder", text: .constant(""))
.frame(minHeight: 30)
.cornerRadius(8.0)
.padding(10)
.background(Color.blue)
Spacer()
.frame(height: keyboardHeight)
【问题讨论】:
您可以将发布者创建为私有属性(没有assignTo
),并使用onReceive
在视图主体中订阅它。我相信这会给你想要的。
【参考方案1】:
错误消息几乎准确地说明了问题所在。但是,尽管您无法访问主体函数(或从主体调用的函数)之外的状态变量,但您可以访问可观察对象。因此,只需通过 @ObservedObject 更改 @State 并定义一个小类,就足以使其工作。
请注意,此解决方案旨在保持您的工作流程理念不变。虽然,还有其他方法可以完成同样的事情。
import SwiftUI
import Combine
class Model: ObservableObject
@Published var keyboardHeight: CGFloat = 0
struct ContentView: View
@ObservedObject var model = Model()
var cancellables: Set<AnyCancellable> = []
init()
NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification)
.merge(with: NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification))
.compactMap( notification in
guard let keyboardFrameValue: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else return nil
let keyboardFrame = keyboardFrameValue.cgRectValue
if keyboardFrame.origin.y == UIScreen.main.bounds.height
return 0
else
return keyboardFrame.height - (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0)
)
.assign(to: \.keyboardHeight, on: model)
.store(in: &cancellables)
var body: some View
VStack
ZStack(alignment: Alignment.bottom)
List
Text("Default text").foregroundColor(Color.red)
TextField("Placeholder", text: .constant(""))
.frame(minHeight: 30)
.cornerRadius(8.0)
.padding(10)
.background(Color.blue)
Spacer()
.frame(height: model.keyboardHeight)
【讨论】:
做同样事情的其他方法?是的,但是这种方式有什么问题吗?以上是关于在主体外访问 SwiftUI 视图中的状态变量的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI Picker 在同一视图中更改第二个状态变量