#swift #xcode #swiftui
#swift #xcode #swiftui
Вопрос:
Я заметил, что кнопки Navigationbar- / Toolbar не работают должным образом, когда есть хотя бы одна переменная @State, которая очень часто обновляет представление.
Я создал простое приложение, чтобы протестировать его.
В приведенном ниже примере кода у вас есть 3 варианта запуска модального листа. Одна кнопка в главном окне, одна на панели инструментов и одна на панели навигации.
Когда мой таймер не обновляет «номер», все 3 кнопки работают должным образом. Когда я запускаю таймер, который будет обновлять вид каждые 0,1 секунды, каждый раз будет работать только кнопка в главном виде. Кнопки на панели инструментов / панели навигации большую часть времени не работают. (Чем короче интервал времени моего таймера, тем меньше кнопок работают)
import SwiftUI
struct ContentView: View {
@State private var number = 0
@State private var showModal = false
func startTimer() {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
number = 1
}
}
var body: some View {
NavigationView {
VStack {
Text("Count (number)")
Button(action: startTimer, label: {
Text("Start Timer")
})
Button(action: { showModal.toggle() }, label: {
Text("Open Modal")
})
}
.navigationBarTitle("Home", displayMode: .inline)
.navigationBarItems(leading:
Button(action: {
showModal.toggle()
}, label: {
Text("Open Modal")
}))
.toolbar {
ToolbarItem(placement: .bottomBar) {
Button(action: {
showModal.toggle()
}, label: {
Text("Open Modal")
})
}
}
}
.sheet(isPresented: $showModal, content: {
Text("Hello, World!")
})
}
}
У кого-нибудь есть идея, есть ли способ заставить 2 кнопки работать должным образом?
Эта проблема возникает с Xcode 12 beta 5 и Xcode Xcode 11.6 (без панели инструментов, поскольку она там недоступна)
Ответ №1:
number
Состояние в предоставленном варианте обновляет все представление, что является результатом проблемы и не очень оптимально для пользовательского интерфейса.
Решение для панели навигации и в целом хорошего стиля заключается в выделении обновляемой части в отдельный вид, поэтому механизм рендеринга SwiftUI перестраивает только ее.
Протестировано с Xcode 12b3 / iOS 14
struct TestOftenUpdate: View {
@State private var showModal = false
var body: some View {
NavigationView {
VStack {
QuickTimerView()
Button(action: { showModal.toggle() }, label: {
Text("Open Modal")
})
}
.navigationBarTitle("Home", displayMode: .inline)
.navigationBarItems(leading:
Button(action: {
showModal.toggle()
}, label: {
Text("Open Modal")
}))
.toolbar {
ToolbarItem(placement: .bottomBar) {
Button(action: {
showModal.toggle()
}, label: {
Text("Open Modal")
})
}
}
}
.sheet(isPresented: $showModal, content: {
Text("Hello, World!")
})
}
}
struct QuickTimerView: View {
@State private var number = 0
var body: some View {
VStack {
Text("Count (number)")
Button(action: startTimer, label: {
Text("Start Timer")
})
}
}
func startTimer() {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
number = 1
}
}
}
С toolbar
другой проблемой — она не работает после открытия первого листа даже без просмотра по таймеру, и вот почему
как видно, расположение кнопок повреждено и находится за пределами области панели инструментов, поэтому тестирование hit завершается неудачей — и это дефект Apple, о котором следует сообщить.
Обходной путь 1:
Поместите панель инструментов за пределы вида навигации (визуально панель инструментов меньше, но иногда может быть уместно, потому что кнопка работает)
NavigationView {
// ... other code
}
.toolbar {
ToolbarItem(placement: .bottomBar) {
Button(action: {
showModal.toggle()
}, label: {
Text("Open Modal")
})
}
}
Комментарии:
1. Большое вам спасибо за помощь. Я всегда помещал только большие представления в собственное автономное представление, а не только Textlabel. Я думаю, мне нужно работать в целом с более отдельными представлениями. Проблема с панелью инструментов, похоже, уже исправлена в Xcode 12b5 / iOS 14. Есть ли способ визуализировать в Xcode / simulator, какие части пользовательского интерфейса повторно отображаются при изменении чего-либо в пользовательском интерфейсе?
Ответ №2:
Xcode 13.1, цель симулятора iPhone 13 (и предварительный просмотр canvas).
Ни одно из других решений не сработало для меня, но я обнаружил, что это влияет только на верхние кнопки навигации и при наличии большого заголовка панели навигации.
Итак, то, что сработало, похоже,:
- Установка встроенного заголовка
.navigationBarTitleDisplayMode(.inline)
- Нет заголовка
- Отсутствует панель инструментов с верхним краем (только нижняя панель)
Если проблема действительно проявилась, я мог бы просмотреть список, содержащийся в представлении (нет необходимости включать функцию обновления), и это также восстановило бы функциональность кнопки.
Комментарии:
1. У меня это сработало хорошо, после того, как все другие параметры не сработали. Спасибо!
2. Я действительно нахожу эту ту же проблему, и установка заголовка панели на встроенный вместо большого заголовка работает для меня.
3. СПАСИБО, этот встроенный модификатор сделал свое дело. Я уже вложил вспомогательные представления и понятия не имел, что это за исправление
4. у меня сработал Xcode 13.2