Ios 在解除MFMailComposeViewController时,如何防止navigationController返回到根目录

Ios 在解除MFMailComposeViewController时,如何防止navigationController返回到根目录,ios,swift3,Ios,Swift3,当我关闭从导航堆栈中的第三个viewController以模式显示的MFMailComposeViewController或MFMessageComposeViewController实例时,导航堆栈将重置,根VC将重新加载。如何防止这种行为并保持在原来的显示视图控制器(堆栈中的第三个VC)上?无论是从演示VC、演示VC还是navigationController调用Dismise,我都会得到相同的行为 以前有人问过这个问题,但我没有看到解决办法 应用程序结构如下所示: TabBarContro

当我关闭从导航堆栈中的第三个viewController以模式显示的MFMailComposeViewController或MFMessageComposeViewController实例时,导航堆栈将重置,根VC将重新加载。如何防止这种行为并保持在原来的显示视图控制器(堆栈中的第三个VC)上?无论是从演示VC、演示VC还是navigationController调用Dismise,我都会得到相同的行为

以前有人问过这个问题,但我没有看到解决办法

应用程序结构如下所示:

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。以下函数在采用MFMailComposeViewController协议的UIViewController扩展中声明

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)

您还可以使用
presentingViewController?进行检查。请退出
方法以获得解决方案

我尝试了以下导航堆栈

我能够从容器VC的“发送电子邮件”按钮成功发送电子邮件,仅使用您的代码

您能检查并验证导航流程吗

如果您仍然面临任何问题,请告诉我。

驳回(动画:true,完成:nil)

self.disclose(动画:true,完成:nil)

试试这个

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


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

我已经用过很多次了


看看这个 . 如果你仍然找不到答案或者无法理解放松的顺序,那么就回答我


希望这能解决您的问题。

我今天发现了导航堆栈的问题。我建立了一个简单的 该项目复制了我的问题项目的tabBarController/NavigationController体系结构,一个组件接一个组件,直到解除MFMailComposeViewController导致我的导航堆栈重置,如我在原始帖子中所述

这立即指向了错误的来源。在我的子类UINavigationCotroller中,我在代码中实例化了根viewController,这样,如果用户在apps设置中设置了一个开关,我就可以跳过一个介绍性视图。为了获取开关设置中的更改,我在navigationController的ViewDidDisplay中调用了我的实例化代码。除了在解雇mailComposeVC时,这一切都很好。修复方法是在ViewDidDisplay中添加一条guard语句,如果NavController 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()
}

您需要提供一些实际的代码,因为我们无法知道您做错了什么。解除逻辑根据调用方是谁以及该调用方是否提供了某些内容而起作用。Dima-请参阅带代码的编辑问题。您是否尝试过
presentingViewController?。解除(self,animated:true)
?对于显示的MFMailComposeViewController,presentingViewController的计算结果为零。对于来自同一父级的其他显示的viewController,presentingViewController的计算结果为顶部TabBarController。当我关闭MFMailComposeViewController时,整个堆栈重置为根。当任何其他显示的viewControllers解除,堆栈不会重置。从TripEditorVC中呈现MFMailComposeViewController后,检查MFMailComposeViewController的presentingViewController是否为零。从同一TripEditoVC呈现的其他模式呈现视图控制器(UIAlertController,SLComposeViewController)报告根TabBarController是其现有的ViewController。当我关闭MFMailComposeViewController时,整个堆栈将重新加载。当我关闭其他显示的ViewController时,堆栈不会重新加载,应用程序将保留在TripEditorVC上。如果您使用的是正确的导航堆栈,则不会为零。请检查您的控制器未从某处分配或未解除分配。