带有动画的 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(错误/崩溃)

带有 TextField 的 Rivers 状态机

带有 Web 视图的模态视图使 iOS7 中的应用程序崩溃

TextField 输入附件视图问题

View Controller 中的两个 TextField 设置为委托,导致应用崩溃,NSRange、范围或索引越界

带有 JNA 的 C 回调使 JRE 崩溃