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 основанное на хранилище вместо более приятного FileDocumentSwiftUI предоставляет. Для этого я в основном сделал следующее:

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)
    }
Другие вопросы по тегам