带有动画的 TextField 使应用程序崩溃并失去焦点
Posted
技术标签:
【中文标题】带有动画的 TextField 使应用程序崩溃并失去焦点【英文标题】:TextField with animation crashes app and looses focus 【发布时间】:2020-02-23 19:32:46 【问题描述】:最小的可重现示例:
在SceneDelegate.swift
:
let contentView = Container()
在ContentView.swift
:
struct SwiftUIView: View
@State var text: String = ""
var body: some View
VStack
CustomTextFieldView(text: $text)
struct Container: View
@State var bool: Bool = false
@State var text: String = ""
var body: some View
Button(action:
self.bool.toggle()
)
Text("Sheet!")
.sheet(isPresented: $bool)
SwiftUIView()
在CustomTextField.swift
:
struct CustomTextFieldView: View
@Binding var text: String
@State var editing: Bool = false
var body: some View
Group
if self.editing
textField
.background(Color.red)
else
ZStack(alignment: .leading)
textField
.background(Color.green)
Text("Placeholder")
.onTapGesture
withAnimation
self.editing = true
var textField: some View
TextField("", text: $text)
问题:
运行上述代码并聚焦文本字段后,应用程序崩溃。我注意到的一些事情:
-
如果我删除
withAnimation
代码或 CustomTextField
文件中的 ZStack
,应用不会崩溃,但 TextField 会失去焦点。
如果我删除 SwiftUIView
中的 VStack
,应用不会崩溃,但 TextField 会失去焦点。
如果我使用 NavigationLink 或在没有工作表的情况下显示 TextField,应用不会崩溃,但 TextField 会失去焦点。
问题:
这是当前版本的 SwiftUI 的问题吗? 是否有使用 SwiftUI 解决此问题的方法?我想远离 尽可能多地查看可表示对象。 由于状态更改而重新计算正文后,如何保持 TextField 的焦点?【问题讨论】:
【参考方案1】:-
正文后如何保持 TextField 的焦点
由于状态变化而重新计算?
你有两个。 两个不同的TextField不能同时处于编辑状态。
Asperi 建议的方法是唯一可行的方法。
你的代码崩溃的原因不容易解释,但在当前的 SwiftUI 中是预期的。
你必须明白,Group 不是一个标准的容器,它就像一个“块”,你可以在上面应用一些修饰符。在 ViewBuilder 中移除 Group 并使用包裹体
struct CustomTextFieldView: View
@Binding var text: String
@State var editing: Bool = false
@ViewBuilder
var body: some View
if self.editing
TextField("", text: $text)
.background(Color.red)
.onTapGesture
self.editing.toggle()
else
ZStack(alignment: .leading)
TextField("", text: $text)
.background(Color.green)
.onTapGesture
self.editing.toggle()
代码将停止崩溃,但还有其他问题,键盘将立即关闭。这是由于应用了轻击手势。
所以,不管你信不信,你只能使用一个 TextField。
struct CustomTextFieldView: View
@Binding var text: String
@State var editing = false
var textField: some View
TextField("", text: $text, onEditingChanged: edit in
self.editing = edit
)
var body: some View
textField.background(editing ? Color.green : Color.red)
根据需要在代码的其他地方使用此自定义文本字段
【讨论】:
我的原始代码中没有 2 个不同的 TextField。我会更新我的问题。 那是你的错误,实际上是你的代码中两个分开的 TextFields 好吧,那么问题是:是否有一个 TextField 方法可以以编程方式聚焦 TextField?答案是否定的。所以我想我将不得不使用 ViewRepresentables。无论如何,崩溃仍然存在。 @CarlesMitjans 有充分的理由,禁止强制用户编辑字段。用户必须决定要编辑哪个字段以及何时编辑。如果您愿意,可以根据需要禁用字段编辑。请参阅 .disabled(bool) 修饰符。 @CarlesMitjans 在这里查看其他解决方案***.com/questions/60379010/… 但要小心,它可能会在下一个版本中停止工作(它使用未记录的 TextFieldStyle)【参考方案2】:为CustomTextFieldView
尝试以下操作(测试并适用于 Xcode 11.2 / ios 13.2)
struct CustomTextFieldView: View
@Binding var text: String
@State var editing: Bool = false
var body: some View
TextField("", text: $text)
.background(self.editing ? Color.red : Color.green)
.onTapGesture
withAnimation
self.editing = true
由于状态改变而重新计算body后如何保持TextField的焦点?
你没有失去焦点,你只是删除了整个文本字段,所以解决方案不是替换文本字段,而是修改它的属性,即背景。放到 ZStack 里面没问题,但要留一个。
【讨论】:
谢谢,它有效。但问题是我必须使用带有 if 块的 ZStack。我将编辑捕获此问题的问题。 withAnimation 有什么用?以上是关于带有动画的 TextField 使应用程序崩溃并失去焦点的主要内容,如果未能解决你的问题,请参考以下文章
删除带有动画的 UITableViewCell(错误/崩溃)