Минимальный воспроизводимый пример (бета-версия Xcode 11.2, работает в Xcode 11.1):
struct Parent: View {
var body: some View {
NavigationView {
Text("Hello World")
.navigationBarItems(
trailing: NavigationLink(destination: Child(), label: { Text("Next") })
)
}
}
}
struct Child: View {
@Environment(\.presentationMode) var presentation
var body: some View {
Text("Hello, World!")
.navigationBarItems(
leading: Button(
action: {
self.presentation.wrappedValue.dismiss()
},
label: { Text("Back") }
)
)
}
}
struct ContentView: View {
var body: some View {
Parent()
}
}
Проблема , кажется, лежит в размещении моих NavigationLink
внутри navigationBarItems
модификатора , что это вложенный внутри зрения SwiftUI, корень которого вид является NavigationView
. Отчет о сбое указывает, что я пытаюсь открыть контроллер представления, который не существует, когда я перемещаюсь вперед Child
и затем обратно Parent
.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Tried to pop to a view controller that doesn't exist.'
*** First throw call stack:
Если бы я вместо этого поместил это NavigationLink
в теле представления, как показано ниже, это работает просто отлично.
struct Parent: View {
var body: some View {
NavigationView {
NavigationLink(destination: Child(), label: { Text("Next") })
}
}
}
Это ошибка SwiftUI или ожидаемое поведение?
РЕДАКТИРОВАТЬ: Я открыл проблему с Apple в их помощник обратной связи с идентификатором FB7423964
на случай, если кто-то из Apple хочет весить :).
РЕДАКТИРОВАТЬ: мой открытый билет в помощнике обратной связи указывает, что есть более 10 аналогичных зарегистрированных проблем. Они обновили разрешение с Resolution: Potential fix identified - For a future OS update
. Скрестим пальцы, что починка скоро приземлится.
РЕДАКТИРОВАТЬ: Это было исправлено в iOS 13.3!
ContentView.swift
. Я внесу изменения в сообщение, но сбой происходит только при переходе вперед, а затем назад.Ответы:
Это было довольно больно для меня! Я оставил его до тех пор, пока большая часть моего приложения не была завершена, и у меня не было места для разборок.
Я думаю, что мы все можем согласиться с тем, что в SwifUI есть кое-что удивительное, но отладка может быть сложной.
На мой взгляд, я бы сказал, что это ошибка. Вот мое обоснование:
Если вы оберните вызов прерывания presentationMode с асинхронной задержкой около полсекунды, вы обнаружите, что программа больше не будет аварийно завершать работу.
Это наводит меня на мысль, что ошибка - это неожиданное поведение в глубине того, как SwiftUI взаимодействует со всем другим кодом UIKit для управления различными представлениями. В зависимости от вашего реального кода, вы можете обнаружить, что если в представлении есть небольшая сложность, сбой фактически не произойдет. Например, если вы отклоняете представление от представления, имеющего список, и этот список пуст, вы получите сбой без асинхронной задержки. С другой стороны, если у вас есть хотя бы одна запись в этом представлении списка, что заставляет итерацию цикла генерировать родительское представление, вы увидите, что сбой не произойдет.
Я не совсем уверен, насколько надежным является мое решение об отложении вызова отклонения. Я должен проверить это намного больше. Если у вас есть идеи по этому поводу, пожалуйста, дайте мне знать! Я был бы очень рад учиться у вас!
источник
.navigationBarItems()
указывает на то, что это ошибка.Это также разочаровало меня в течение довольно долгого времени. За последние несколько месяцев, в зависимости от версии Xcode, версии симулятора и реального типа устройства и / или версии, он перешел от работы к отказу в работе снова, по-видимому, наугад. Однако в последнее время он постоянно терпел неудачу, поэтому вчера я глубоко погрузился в это. В настоящее время я использую версию Xcode 11.2.1 (11B500).
Похоже, что проблема вращается вокруг панели навигации и способа добавления кнопок к нему. Поэтому вместо использования NavigationLink () для самой кнопки я попытался использовать стандартную Button () с действием, которое устанавливает переменную @State, которая активирует скрытый NavigationLink. Вот замена для родительского представления Роберта:
Для меня это работает очень последовательно на всех симуляторах и на всех реальных устройствах.
Вот мои взгляды помощника:
Вот пример использования:
источник
Это серьезная ошибка, и я не могу найти правильный способ обойти ее. Работало нормально в iOS 13 / 13.1 но 13.2 вылетает.
Вы можете фактически воспроизвести это намного более простым способом (этот код буквально все, что вам нужно).
Надеюсь, что Apple разберется с этим, так как он наверняка сломает множество приложений SwiftUI (включая мое).
источник
В качестве обходного пути, основываясь на ответе Чака Х, я инкапсулировал NavigationLink как скрытый элемент:
Затем вы можете использовать его в NavigationView (что крайне важно) и вызывать его с помощью кнопки на панели навигации:
Оберните это в комментарии "// HACK", чтобы, когда Apple исправит это, вы могли заменить его.
источник
Основываясь на информации, которую вы, ребята, предоставили, и особенно на комментарии @Robert о размещении NavigationView, я нашел способ обойти проблему, по крайней мере, в моем конкретном сценарии.
В моем случае у меня был TabView, который был заключен в NavigationView следующим образом:
Этот код вылетает, поскольку все сообщают в iOS 13.2 и работают в iOS 13.1. После некоторых исследований я нашел способ обойти эту ситуацию.
По сути, я перемещаю NavigationView на каждый экран отдельно на каждой вкладке следующим образом:
Каким-то образом идет вразрез с предпосылкой простоты SwiftUI, но она работает на iOS 13.2.
источник
Xcode 11.2.1 Swift 5
ПОНЯЛ! Мне понадобилось пару дней, чтобы понять это ...
В моем случае при использовании SwiftUI я получаю сбой, только если нижняя часть моего списка выходит за пределы экрана, а затем я пытаюсь «переместить» любые элементы списка. В итоге я обнаружил, что если у меня слишком много «материала» под List (), то он падает на ходу. Например, ниже моего List () у меня были Text (), Spacer (), Button (), Spacer () Button (). Если я закомментировал ОДИН из этих объектов, то внезапно не смог воссоздать аварию. Я не уверен, каковы ограничения, но если вы получаете этот сбой, то попробуйте удалить объекты из списка ниже, чтобы посмотреть, поможет ли это.
источник
Хотя я не вижу сбоев, у вашего кода есть некоторые проблемы:
устанавливая ведущий элемент, вы фактически убиваете поведение переходов навигации по умолчанию. (попробуйте провести пальцем от лицевой стороны, чтобы увидеть, работает ли он).
Так что не нужно иметь там кнопку. Просто оставьте все как есть, и у вас будет бесплатная кнопка возврата.
И не забывайте, согласно HIG , заголовок кнопки «Назад» должен показывать, куда он идет, а не то , что он есть! Поэтому постарайтесь установить заголовок для первой страницы, чтобы показать ее любой всплывающей кнопкой.
источник
FWIW - вышеупомянутые решения, предполагающие скрытый взлом NavigationLink, по-прежнему остаются лучшим обходным путем в iOS 13.3b3. Я также подал FB7386339 для потомков и был закрыт, как и другие вышеупомянутые FB: «Обнаружено потенциальное исправление - для будущего обновления ОС».
Скрещенные пальцы.
источник
Это решено в iOS 13.3. Просто обновите свою ОС и xCode.
источник
.buttonStyle(PlainButtonStyle())
модификатор NavigationLink и попробуйте снова. дайте мне знать, если вы задали вопрос.