Swift UI 2 DocumentGroup получает действия кнопок панели навигации
Я использую новую сцену DocumentGroup для проекта iOS 14 (в настоящее время работающего над бета-версией), и я действительно не знаю, как я могу обнаруживать события на панели навигации, такие как нажатие '<' или назад (см. Экран) предопределенная панель навигации сцены "DoucmentGroup". Для пользовательских кнопок это возможно, и также не составляет большого труда изменить стиль полосы (например, серый). Я попытался отключить кнопку, добавив новые кнопки на панель навигации и т. Д. Следующий пример представляет собой стандартный код, когда вы собираетесь создать новое приложение на основе документа в Xcode:
@main struct DocumentAppApp: App {
@SceneBuilder var body: some Scene {
// Adding of a new document
DocumentGroup(newDocument: DocumentAppDocuments()) { file in
ContentView(document: file.$document) // .navigationBarBackButtonHidden(true)
}
}
}
struct ContentView: View {
@Binding var document: DocumentAppDocuments
var body: some View {
TextEditor(text: $document.text)
}
}
3 ответа
В итоге я сделал следующее в своем документе ContentView.body
:
NavigationView {
SideBar(document: $document)
.navigationBarItems(leading: Button("Back") {
// figure out how to programmatically go back...
})
Text("Nothing selected")
}
.navigationBarHidden(true)
Я по сути убил автомат NavigationView
который поставляется с браузером документов. Это не идеально по многим причинам, первая из которых состоит в том, что я еще не придумал, как вернуться назад. Если бы у нас был доступ к базовомуNavigationView
чтобы я мог настроить свою боковую панель и свой контент, это не было бы проблемой, но и здесь я тоже не добился успеха.
DocumentGroup
отчасти похоже на полусырой мусор. Почему он подталкивает, а не показывает "пустой" документ? Почему я не могу установить цвет акцентаDocumentGroup
и т. д. Я написал отзывы об этих элементах, но кто знает, будут ли они рассмотрены до выпуска.
Последний вариант - взять это на себя и не использовать DocumentGroup
вообще, используйте UIDocumentBrowserViewController
как UIViewControllerRepresentable
и продолжай жить своей жизнью. Я, наверное, скоро здесь окажусь.
ОБНОВЛЕНИЕ: я бросил DocumentGroup
. В этом нет никакого смысла. Продвигаете контент? Тупой. Меняется цвет оттенка? Не могу. Мое приложение также избавилось от записи приложения SwiftUI, поэтому я могу полностью контролировать UIDocumentBrowserViewController, и я предлагаю вам сделать то же самое. Единственной сложной задачей было выяснить, как лучше всего использоватьUIDocument
основанное на хранилище вместо более приятного FileDocument
SwiftUI предоставляет. Для этого я в основном сделал следующее:
final class Document: UIDocument, ObservableObject {
var someDocumentProperty: String = "" {
willSet {
// this updates the SwiftUI view hierarchy
objectWillChange.send()
} didSet {
// this will autosave whenever you change this property
updateChangeCount(.done)
}
}
}
Теперь он будет полностью работать с представлениями SwiftUI, правильно сохранять все.
Точно такая же проблема. Короче говоря, я решил посмотреть, создается ли еще UIApplication.shared, и когда он был создан, я смог программно вернуться к следующему:
private func goBack() {
#if canImport(UIKit)
guard let currentWindow = UIApplication.shared.windows.first,
let documentBrowser = currentWindow
.rootViewController as? UIDocumentBrowserViewController
else
{
logw(
"<\(#fileID) \(#function)> Failed to retrieve document browser."
)
return
}
documentBrowser.dismiss(animated: true) {
logi("<\(#fileID) \(#function)> the document browser has dismissed it's child.")
}
#endif
}
или упрощенно:
`UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true) { print("the document browser has dismissed it's child.") }`
Моя цель состоит в том, чтобы внедрить собственную функциональность, сохранив при этом внешний вид системной кнопки «Назад», предоставляемой
DocumentGroup
. Обратите внимание, что мой вид документа
UIViewController
, завернут в
UIViewControllerRepresentable
. Решение, основанное на Джейсоне Кардуэлле:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
var systemBackButtonItem = navigationController?.navigationBar.items?[0].leftBarButtonItems?[0]
systemBackButtonItem?.target = self
systemBackButtonItem?.action = #selector(done)
}
@objc private func done() {
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true) {
print("the document browser has dismissed it's child.")
}
}
Однако будьте осторожны, это может конфликтовать с некоторыми функциями, предоставляемыми DocumentGroup. Впрочем, пока в моем случае все хорошо. Другой вариант:
private weak var originalBackButtonTarget: AnyObject?
private var originalBackButtonAction: Selector?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
var systemBackButtonItem = navigationController?.navigationBar.items?[0].leftBarButtonItems?[0]
originalBackButtonTarget = systemBackButtonItem?.target
systemBackButtonItem?.target = self
originalBackButtonAction = systemBackButtonItem?.action
systemBackButtonItem?.action = #selector(done)
}
@objc private func done() {
guard let originalBackButtonAction = originalBackButtonAction else { return }
originalBackButtonTarget?.perform(originalBackButtonAction, with: self)
}