Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios SwiftUI中的UITextField导致;在视图更新期间修改状态,这将导致未定义的行为。”;_Ios_Swift_Swiftui_Uitextfield - Fatal编程技术网

Ios SwiftUI中的UITextField导致;在视图更新期间修改状态,这将导致未定义的行为。”;

Ios SwiftUI中的UITextField导致;在视图更新期间修改状态,这将导致未定义的行为。”;,ios,swift,swiftui,uitextfield,Ios,Swift,Swiftui,Uitextfield,我试图在SwiftUI中创建一个系统,让我可以控制哪个textfield是第一个响应者,这样我就可以轻松创建一个响应者链 我创建了一个UIViewRepresentable,它获取一个带有布尔类型的绑定的环境值,并且我正在根据这些函数更改状态textFieldDidBeginEditing和textFieldDidEndEditing struct TextField: UIViewRepresentable { @Binding var text: String @Envi

我试图在SwiftUI中创建一个系统,让我可以控制哪个textfield是第一个响应者,这样我就可以轻松创建一个响应者链

我创建了一个
UIViewRepresentable
,它获取一个带有布尔类型的
绑定
的环境值,并且我正在根据这些函数更改状态
textFieldDidBeginEditing
textFieldDidEndEditing

struct TextField: UIViewRepresentable {
 
    @Binding var text: String
    @Environment(\.isSecureField) var isSecureField: Bool
    @Environment(\.isFirstResponder) var isFirstResponder: Binding<Bool>?
    @Environment(\.placeholder) var placeholder: String?
    @Environment(\.keyboardType) var keyboardType: UIKeyboardType
    @Environment(\.returnKeyType) var returnKeyType: UIReturnKeyType
    @Environment(\.textContentType) var contentType: UITextContentType?
    @Environment(\.autoCapitalization) var  autoCapitalization: Bool
    @Environment(\.autoCorrection) var  autoCorrection: Bool
    @Environment(\.font) var font: Font?
    
    let onCommit: (() -> Bool)?
    
    init(
        text: Binding<String>,
        onCommit:(() -> Bool)? = nil) {

        self._text = text
        self.onCommit = onCommit
    
    }
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.delegate = context.coordinator
        syncValues(context: context, textField: textField)
        return textField
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        syncValues(context: context, textField: uiView)
 
        if let isFirstReposnderValue = isFirstResponder?.wrappedValue {
            switch isFirstReposnderValue {
            case true:
                uiView.becomeFirstResponder()
            case false:
                uiView.resignFirstResponder()
            }
        }
    }
    
    private func syncValues(context: Context, textField: UITextField) {
        textField.text = text
        textField.isSecureTextEntry = isSecureField
        textField.textContentType = contentType
        textField.keyboardType = keyboardType
        textField.placeholder = placeholder
        textField.font = UIFont.preferredFont(from: font)
        textField.autocapitalizationType = autoCapitalization ? .sentences : .none
        textField.returnKeyType = returnKeyType
        textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        textField.autocorrectionType = autoCorrection ? .yes : .no
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator( parent: self  )
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        
        private let parent: TextField
        
        init(parent: TextField) {
            self.parent = parent
        }
        
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            return parent.onCommit?() ?? true
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            parent.$text.wrappedValue = textField.text ?? ""
        }

        func textFieldDidBeginEditing(_ textField: UITextField) {
            parent.isFirstResponder?.wrappedValue =  true

        }

        func textFieldDidEndEditing(_ textField: UITextField) {
            parent.isFirstResponder?.wrappedValue =  false
        }

    }
}
但我得到了:

在视图更新期间修改状态,这将导致未定义的行为

extension Binding where Value == Bool {
    
    init<V: Hashable>(tag: V, selection: Binding<V?>) {
        self.init { () -> Value in
            selection.wrappedValue == tag
        } set: { (newValue) in
            selection.wrappedValue = newValue ?  tag : nil
        }
    }
}
class TestLoginViewModel:ObservableObject {
    
    @Published var email: String = ""
    @Published var password: String = ""
}

struct TestLoginView: View {
    
    enum Field {
        case email
        case password
    }
    
    @StateObject private var viewModel: TestLoginViewModel
    @State private var activeField: Field?
    
    init(viewModel: TestLoginViewModel = .init()) {
        self._viewModel = StateObject(wrappedValue: viewModel)
    }
  
    
    var body: some View {
        VStack(spacing: 8) {
            
            TextField(text: $viewModel.email, onCommit: { () -> Bool in
                activeField = .password
                return true
            })
            .placeholder(L10n.email)
            .isFirstReponder(.init(tag: .email, selection: $activeField))
            .returnKeyType(.next)
            .keyboard(.emailAddress)
            
            TextField(text: $viewModel.password, onCommit: { () -> Bool in
                activeField = nil
                return true
            })
            .placeholder(L10n.password)
            .isSecureField(true)
            .isFirstReponder(.init(tag: .password, selection: $activeField))
            .returnKeyType(.send)
            .keyboard(.emailAddress)
        }
    }
}