#xcode #swiftui #ios15
Вопрос:
У меня есть следующий код:
struct Credential: Equatable {
var username = ""
var password = ""
}
enum Database {
static var credential = Credential()
}
struct UsernamePasswordInput: View {
@Binding var credential: Credential
var body: some View {
Group {
TextField("Username", text: self.$credential.username)
SecureField("password", text: self.$credential.password)
}
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
struct Login: View {
private var credential: Binding<Credential>
var body: some View {
UsernamePasswordInput(credential: self.credential)
}
init() {
self.credential = Binding<Credential>(
get: {
Database.credential
}, set: { newValue in
Database.credential = newValue
}
)
}
}
struct ContentView: View {
var body: some View {
Login()
}
}
При запуске этого кода из Xcode 13.0 на устройстве iOS 15 Binding<String> action tried to update multiple times per frame.
в консоли Xcode появляется сообщение. Это происходит всякий раз, когда вы вводите символ либо в TextField
, либо в SecureField
. Сообщение не отображается на устройствах iOS 13 или 14.
Я знаю, что могу решить эту проблему, просто используя a @StateObject
, но приведенный выше код отражает структуру более крупного проекта. Мой вопрос в следующем: сообщение Xcode каким-то образом указывает на проблему? Является ли приведенный выше код каким-то принципиально неверным?
Комментарии:
1. Вполне вероятно, что обычай инициализирован. SwiftUI не очень хорошо справляется с ними. Он может решить перезагрузить весь вид, когда захочет. Вместо пользовательской привязки просто используйте обычную привязку. Это похоже на оксюморон, когда частная переменная хакерски обновляется извне.
2. @loremipsum К вашему сведению: я переместил создание привязки в представлении входа в систему в экземпляр представления UsernamePasswordInput, и это не удалило сообщение.
Ответ №1:
Вот возможный безопасный обходной путь — используйте встроенную разделенную привязку для каждого текстового поля:
struct UsernamePasswordInput: View {
@Binding var credential: Credential
var body: some View {
Group {
TextField("Username", text: Binding(
get: { credential.username },
set: { credential.username = $0 }
))
SecureField("password", text: Binding(
get: { credential.password },
set: { credential.password = $0 }
))
}
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
Протестировано с Xcode 13 / iOS 15
Комментарии:
1. Да, так оно и было. Очевидно, разница в том, что мой код привязывается к структуре, а ваш код привязывается к строке этой структуры. Можете ли вы объяснить, почему было неправильно привязываться к структуре вне представления?