【问题标题】:How do I prevent a navigationController from returning to root when dismissing MFMailComposeViewController关闭 MFMailComposeViewController 时如何防止导航控制器返回根目录
【发布时间】:2017-11-19 15:52:52
【问题描述】:

当我关闭从导航堆栈中的第三个 viewController 模态呈现的 MFMailComposeViewController 或 MFMessageComposeViewController 实例时,导航堆栈被重置,并且根 VC 被重新加载。如何防止这种行为并保留在原始呈现视图控制器(堆栈中的第三个 VC)上?无论我从呈现的 VC、呈现的 VC 还是 navigationController 调用dismiss,我都会得到相同的行为。

以前有人问过这个问题,但我没有看到解决方案。

应用结构如下所示:

TabBarController
Tab 1 - TripsNavController
    -> Trips IntroductionVC (root VC) segue to:
    -> TripsTableViewController segue to:
    -> TripEditorContainerVC
         - TripEditorVC (child of ContainerVC)
         - HelpVC (child of ContainerVC)
Tab 2...
Tab 3...
Tab 4...

在 TripEditorVC 中,我展示了 MFMailComposeViewController。下面的函数是在 UIViewController 的扩展中声明的,它采用了 MFMailComposeViewControllerDelegate 协议

func shareWithEmail(message: NSAttributedString) {

    guard MFMailComposeViewController.canSendMail() else {
        showServiceError(message: "Email Services are not available")
        return
    }

    let composeVC = MFMailComposeViewController()
    composeVC.setSubject("My Trip Plan")
    composeVC.setMessageBody(getHTMLforAttributedString(attrStr: message), isHTML: true)
    composeVC.mailComposeDelegate = self

    present(composeVC, animated: true, completion: nil)

}

然后在委托方法中我关闭 MFMailComposeVC:

public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {

    switch result {
    case .sent:
        print("Mail sent")
    case .saved:
        print("Mail saved")
    case .cancelled:
        print("Mail cancelled")
    case .failed:
        print("Send mail failed")
    }

    if error != nil {

       showServiceError(message: "Error: \(error!.localizedDescription)")
    }

    dismiss(animated: true, completion: nil)
}

我尝试了以下方法来呈现和关闭并获得相同的行为,即:TripsNavController 清除导航堆栈并将 TripsIntroductionVC 作为其根 VC 重新加载:

self.present(composeVC, animated: true, completion: nil)
self.parent?.present(composeVC, animated: true, completion: nil)
self.parent?.navigationController?.present(composeVC, animated: true, completion: nil)
self.navigationController?.present(composeVC, animated: true, completion: nil)

【问题讨论】:

  • 您需要提供一些实际代码,因为我们无法知道您做错了什么。 Dismiss 逻辑的工作原理取决于调用者是谁以及调用者是否提供了某些内容。
  • Dima - 用代码查看已编辑的问题。
  • 你试过presentingViewController?.dismiss(self, animated: true)吗?
  • 对于呈现的 MFMailComposeViewController,presentingViewController 的计算结果为 nil。对于来自同一父级的其他呈现的 viewController,presentingViewController 的计算结果是顶部的 TabBarController。当我关闭 MFMailComposeViewController 时,整个堆栈被重置为 root。当任何其他呈现的 viewController 被解除时,堆栈不会重置。

标签: ios swift3


【解决方案1】:

您也可以通过presentingViewController?.dismiss方法查看解决方案。

我已尝试使用以下导航堆栈。

我只能使用您的代码从 Container VC 的发送电子邮件按钮成功发送电子邮件。

能否请您检查并验证导航流程?

如果您仍然遇到任何问题,请告诉我。

【讨论】:

  • 从 TripEditorVC 中呈现 MFMailComposeViewController 后,对 MFMailComposeViewController 的presentingViewController 的检查为零。从同一 TripEditoVC(UIAlertController、SLComposeViewController)呈现的其他模态呈现视图控制器报告根 TabBarController 是它们的呈现视图控制器。当我关闭 MFMailComposeViewController 时,会重新加载整个堆栈。当我关闭其他显示的 viewController 时,堆栈不会重新加载,并且应用程序仍保留在 TripEditorVC 上。
  • 如果您使用正确的导航堆栈,那么它不会为零。请检查您的控制器是否未从某处分配或未解除分配。
【解决方案2】:

解雇(动画:真,完成:无)

self.dismiss(动画:真,完成:无)

试试这个

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController =     storyboard.instantiateViewControllerWithIdentifier("secondViewControllerId") as! SecondViewController
self.presentViewController(secondViewController, animated: true, completion: nil)

https://stackoverflow.com/a/37740006/8196100

【讨论】:

    【解决方案3】:

    只需使用 Unwind Segue,它在您的情况下非常简单和完美

    我用过很多次了..


    看看这个Unwind segue's example .如果您仍然无法找到答案或无法理解 Unwind segue,请回复我。

    希望这能解决您的问题。

    【讨论】:

      【解决方案4】:

      我今天发现我的导航堆栈有问题。我建立了一个简单的 该项目逐个组件地复制了我的问题项目的 tabBarController/NavigationControler 架构,直到关闭 MFMailComposeViewController 导致我的导航堆栈按照我的原始帖子中的描述重置。

      这立即指出了错误的根源。在我的子类 UINavigationCotroller 中,我在代码中实例化了根 viewController,以便如果用户在应用程序设置中设置了开关,我可以跳过介绍性视图。为了获取该开关设置中的更改,我在 navigationController 的 viewDidAppear 中调用了我的实例化代码。除了关闭 mailComposeVC 时,它工作得很好。修复方法是在 viewDidAppear 中添加一个保护语句,以在 navControllers viewController 集合不为空时返回,并在切换更改时发送并响应 NSNotification。

      类 TopNavigationController: UINavigationController {

      var sectionType: SectionType?
      var defaults = UserDefaults.standard
      var showIntroFlag: Bool = true
      
      override func viewDidLoad() {
          super.viewDidLoad()
      
          // Handle initial load of the tab bar controller where we are not sent a sectionType
          if sectionType == nil {
              sectionType = .groups
          }
      
          setShowIntroFlag()
      
          NotificationCenter.default.addObserver(self, selector: #selector(resetControllers), name: NSNotification.Name(rawValue: "kUserDidChangeShowIntros"), object: nil)
      }
      
      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(true)
      
          guard self.viewControllers.isEmpty else {
              return
          }
      
          loadControllers()
      }
      
      func setShowIntroFlag() {
          showIntroFlag = true
      
          // Check NSUserDefaults to see if we should hide the Intro Views for all sections
          if defaults.bool(forKey: "SHOW_SECTION_INTROS") == false {
              showIntroFlag = false
          }
      }
      
      func loadControllers() {
          if showIntroFlag == true {
              showIntro()
          } else {
              skipIntro()
          }
      }
      
      func resetControllers() {
          setShowIntroFlag()
          loadControllers()
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-29
        • 1970-01-01
        • 1970-01-01
        • 2015-05-10
        • 1970-01-01
        • 2017-12-10
        • 2020-03-30
        • 1970-01-01
        相关资源
        最近更新 更多