Страница, созданная MFMailComposeViewController, не может быть отображена из-за иерархии - Swift 4 - PullRequest
0 голосов
/ 28 мая 2018

Я пытаюсь добавить функцию, то есть почтовая страница всплывет после того, как пользователь коснется строки в таблице.А именно, это означает, что пользователь может активировать «функцию» (здесь имя этой функции - «orderOfSendAnEmailToReportTheProblem»), когда строка повернута.Все мои коды были показаны ниже.(Этот вид кода был предложен несколькими гениями в Stackoverflow ...)

import Foundation
import UIKit
import MessageUI

class ReportProblem : UIViewController, MFMailComposeViewControllerDelegate {

func orderOfSendAnEmailToReportTheProblem() {
    let mailComposeViewController = configureMailController()
    if MFMailComposeViewController.canSendMail() {
    self.present(mailComposeViewController, animated: true, completion: nil)
    } else {
        showMailError()
    }
}
//Activate the series of the commands of sending the email.


func configureMailController() -> MFMailComposeViewController {
    let mailComposeVC = MFMailComposeViewController()
    mailComposeVC.mailComposeDelegate = self

    mailComposeVC.setToRecipients(["my email"])
    mailComposeVC.setSubject("Yo")

    return mailComposeVC
}
//Set the recipient and the title of this email automatically.

func showMailError() {
    let sendMailErrorAlert = UIAlertController(title: "Could not sned the email.", message: "Oops, something was wrong, please check your internet connection once again.", preferredStyle: .alert)
    let dismiss = UIAlertAction(title: "Ok", style: .default, handler: nil)
    sendMailErrorAlert.addAction(dismiss)
    self.present(sendMailErrorAlert, animated: true, completion: nil) //If you conform the protocol of NSObject instead of UIViewController, you could not finish this line successfully.
}
//Set a alert window so that it would remind the user when the device could not send the email successfully.

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    controller.dismiss(animated: true, completion: nil)
}
//Set this final step so that the device would go to the previous window when you finish sending the email.
}

Однако возникла проблема.Когда я тестирую его на своем реальном устройстве, и после того, как я коснулся этой конкретной строки, ничего не произошло, никакие новые страницы не всплыли ... Xcode только показал, что «Предупреждение: Попытка представить, чье представление не находится в иерархии окон!"Я пробовал несколько способов, таких как «view.bringSubview (toFront: mailComposeVC)» или добавление кодов, показанных ниже в конце моих кодов, но ничего не получалось.

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

Я заметил, что некоторые другие люди также сталкиваются с подобными проблемами, когда они хотят создать окно оповещения, и решение этой проблемы заключается в создании независимого UIWindow, но я хочу использовать mailComposeController для представленияадрес электронной почты вместо.Некоторые другие также столкнулись с некоторыми проблемами, связанными с MFMailComposeViewController, но их проблемы не относятся к иерархии.Я был новичком в swift, и меня эта проблема преследовала целый день ... Я использовал swift 4 для разработки своего приложения, кто-нибудь знает, как решить эту проблему здесь? ...

Ответы [ 3 ]

0 голосов
/ 29 мая 2018

Гений Вивек Сингх, ваш образ выглядит хорошо, но это немного утомительно.Более того, он все еще не работал в моем проекте ... (Похоже, вы использовали некоторые коды об UIView, такие как parentView, childView и view. Однако я использовал MFMailComposeViewController, который выглядит какнемного отличается от первоначального взгляда ... Я не уверен, верна ли эта теория или нет ...)

Однако я нашел решение.Я предполагаю, что проблема заключается в том, что после того, как пользователь щелкнул строку в другом tableViewController (здесь SettingTVController), он активирует функцию "orderOfSendAnEmailToReportTheProblem( )", которая находится в "другом" viewController (здесь ReportProblem).Поскольку существует два разных viewController, возник некоторый конфликт.

Поэтому я перенесу все свои коды, которые я разместил в предыдущем вопросе, в свой оригинальный tableViewController, чтобы пользователь не переходил в другой viewController при активации функции, и проблема с иерархией больше не возникает.

import UIKit
import StoreKit
import MessageUI

class SettingTVController: UITableViewController, MFMailComposeViewControllerDelegate {

var settingTitleConnection = showData()

override func viewDidLoad() {
    //skip
}

override func didReceiveMemoryWarning() {
   //skip
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   //skip
}

override func numberOfSections(in tableView: UITableView) -> Int {
    //skip
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
   //skip
}



override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    if tableView.indexPathForSelectedRow?.row == 2 && tableView.indexPathForSelectedRow?.section == 1 {
        orderOfSendAnEmailToReportTheProblem()
    } else {
      //skip
    }

    tableView.deselectRow(at: indexPath, animated: true)
}

//-----<The codes below is used to construct the function of reporting problem with email>-----
func orderOfSendAnEmailToReportTheProblem() {
    let mailComposeViewController = configureMailController()
    self.present(mailComposeViewController, animated: true, completion: nil)
    if MFMailComposeViewController.canSendMail() {
        self.present(mailComposeViewController, animated: false, completion: nil)
    } else {
        showMailError()
    }
}
//Activate the series of the commands of sending the email.

func configureMailController() -> MFMailComposeViewController {
    let mailComposeVC = MFMailComposeViewController()
    mailComposeVC.mailComposeDelegate = self

    mailComposeVC.setToRecipients(["datototest@icloud.com"])
    mailComposeVC.setSubject("Reporting of Problems of Rolling")

    return mailComposeVC
}
//Set the recipient and the title of this email automatically.

func showMailError() {
    let sendMailErrorAlert = UIAlertController(title: "Could not send the email.", message: "Oops, something was wrong, please check your internet connection once again.", preferredStyle: .alert)
    let dismiss = UIAlertAction(title: "Ok", style: .default, handler: nil)
    sendMailErrorAlert.addAction(dismiss)
    self.present(sendMailErrorAlert, animated: true, completion: nil) //If you conform the protocol of NSObject instead of UIViewController, you could not finish this line successfully.
}
//Set a alert window so that it would remind the user when the device could not send the email successfully.

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    controller.dismiss(animated: true, completion: nil)
    //UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: true, completion: nil)
}
//Set this final step so that the device would go to the previous window when you finish sending the email.
//-----<The codes above is used to construct the function of reporting problem with email>-----
}

Я разместил свои коды выше, чтобы они могли помочь другим, кто когда-нибудь столкнется с подобной проблемой.Еще раз спасибо за вашу помощь !!

0 голосов
/ 16 октября 2018

Я не знаю, почему вы столкнулись с проблемой иерархии представлений.Но я могу достичь опции общего доступа к почте в swift 4. Я выполнил точно такие же шаги.

  1. Проверка возможности отправки почты:

    MFMailComposeViewController.canSendMail ()

  2. Настроить почтовое тело:

    private func configureMailController() -> MFMailComposeViewController {
    let mailComposeViewController = MFMailComposeViewController()
    mailComposeViewController.mailComposeDelegate = self
    mailComposeViewController.setMessageBody("MESSAGE BODY", isHTML: true)
    return mailComposeViewController
    

    }

  3. Подарочный VC:

    present(mailComposeViewController, animated: true)

  4. подтвердите необязательный протокол и явно отклоните представление:

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    controller.dismiss(animated: true)
    

    }

0 голосов
/ 28 мая 2018

Так что теперь я пишу другой способ представления, который я использую для общих видов.Добавьте некоторый код в другой класс для представления представления, чтобы их можно было повторно использовать в приложении с помощью этих двух методов.

func slideInFromRight(parentView:UIView,childView:UIView) {
    childView.transform = CGAffineTransform(translationX: parentView.frame.maxX, y: 0)
    parentView.addSubview(childView)
    UIView.animate(withDuration: 0.25, animations: {
        childView.transform = CGAffineTransform(translationX: 0, y: 0)
    })
}

func slideOutToRight(view:UIView) {
    UIView.animate(withDuration: 0.25, animations: {
        view.transform = CGAffineTransform(translationX: view.frame.maxX, y: 0)
    },completion:{(completed:Bool) in
        view.removeFromSuperview()
    })
}

Теперь используйте эти методы для представления и удаления настраиваемого контроллера представления следующим образом

let window = UIApplication.shared.keyWindow
let vc = YourViewController().instantiate()
self.addChildViewController(vc)
let view = vc.view

view.frame = CGRect(x: 0, y: 20, width: window!.frame.width, height: window!.frame.height-20)
//Here Animation is my custom presenter class and shared is it's shared instance.

Animation.shared.slideInFromRight(parentView: window!, childView: view)

//Or you can use current View controller's view 
Animation.shared.slideInFromRight(parentView: self.view!, childView: view)
...