简体   繁体   English

SwiftUI TextField 在设置样式时失去焦点

[英]SwiftUI TextField loses focus when styled

I'm trying to apply some validation to a TextField to add a red border around the field when the content is invalid (in this case, I'm validating that the content is a positive number that is less than the specified maxLength ).我正在尝试对 TextField 应用一些验证,以便在内容无效时在字段周围添加一个红色边框(在这种情况下,我正在验证内容是一个小于指定maxLength的正数)。

The validation works fine and the border is applied when the value is out of range.验证工作正常,当值超出范围时应用边框。 However, when the border is applied to the TextField, the TextField loses focus in the UI (and also loses focus when the border is removed).但是,当边框应用于 TextField 时,TextField 在 UI 中失去焦点(并且在移除边框时也会失去焦点)。

Here is a snippet of my code (I've included some extensions I'm using, but I don't think those are relevant to the issue)这是我的代码片段(我包含了一些我正在使用的扩展,但我认为这些与问题无关)

import Foundation
import SwiftUI
import Combine

struct MyView : View {
    @Binding var value: Int
    var label: String
    var maxLength: Int
    
    @State private var valid: Bool = true
    
    var body: some View {
        TextField(label, value: $value, format: .number)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .fixedSize()
            .multilineTextAlignment(.trailing)
            .onReceive(Just(value), perform: validate)
            .if(!valid, transform: { $0.border(.red)})
    }
    
    func validate(val: Int) {
        let newVal = val.clamped(to: 0...maxLength)
        if newVal != val {
            valid = false
        } else {
            valid = true
        }
    }
}

extension View {
    @ViewBuilder
    func `if`<Transform: View>(_ condition: Bool, transform: (Self) -> Transform) -> some View {
        if condition { transform(self) }
        else { self }
    }
}

extension Comparable {
    func clamped(to limits: ClosedRange<Self>) -> Self {
        return min(max(self, limits.lowerBound), limits.upperBound)
    }
}

Is there any way to preserve focus on the TextField when styles are conditionally applied to it?当有条件地应用 styles 时,有什么方法可以保持对 TextField 的关注?

Or am I approaching validation wrong altogether?还是我完全错误地接近验证? Is there a better way to check fields and apply conditional styling?有没有更好的方法来检查字段并应用条件样式?

Because of the way your if modifier is structured, SwiftUI is unable to see that the underlying View is the same in the two conditions.由于if修饰符的结构方式,SwiftUI 无法看到底层View在两种情况下是相同的。 For more detail on this, I'd suggest you watch Demystifying SwiftUI from WWDC 2021 .有关这方面的更多详细信息,我建议您观看WWDC 2021 的 Demystifying SwiftUI

One solution is the simplify your border modifier into the following:一种解决方案是将您的border修饰符简化为以下内容:

.border(valid ? .clear : .red)

This way, SwiftUI can still tell that this is the same underlying View .这样, SwiftUI 仍然可以看出这是相同的底层View

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM