1

I try to present message format in main menu class from emergency class, but it doesn't present anything and this what Xcode keep telling me

Warning: Attempt to present <MFMessageComposeViewController: 0x13703dc00> on <Emergency: 0x1365a4b60> whose view is not in the window hierarchy!
Warning: Attempt to present <MFMessageComposeViewController: 0x13703dc00>  on <MainMenu: 0x136649fd0> which is already presenting (null)

here's the code

MainMenu class

class MainMenu: UIViewController{

    let getHelp:Emergency = Emergency()
    @IBAction func TapOnEmergency(sender: UIButton) {


         getHelp.emergencyMessage()

        getHelp.presentViewController(getHelp.messageComposer,animated: false,completion: nil)

        dispatch_async(dispatch_get_main_queue(), {
            self.presentViewController(self.getHelp.messageComposer, animated: true, completion: nil)
        })
    }
    }

Emergency class

class Emergency: UIViewController,MFMessageComposeViewControllerDelegate{

    func emergencyMessage()
    {

         let textMessageRecipients = [number!]



                if (MFMessageComposeViewController.canSendText() ) {
                    messageComposer.recipients = textMessageRecipients
                    messageComposer.body = ""
                    messageComposer.messageComposeDelegate = self
                   presentViewController(messageComposer,animated: false,completion: nil)

        } else {

    let errorAlert = UIAlertController(title: "Cannot Send Text Message", message: "Your device is not able to send text messages.", preferredStyle: UIAlertControllerStyle.Alert)

    errorAlert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: nil))

    self.presentViewController(errorAlert, animated: true, completion: nil)

        }


    }

How I can fix this problem?

note that emergency has no scene/view

rmaddy
  • 314,917
  • 42
  • 532
  • 579
O user
  • 97
  • 1
  • 11
  • Why do you have two `presentViewController` calls together? That doesn't look right. Actually you have three because `getHelp.emergencyMessage()` is trying to present a viewController too. – Michael Feb 11 '16 at 02:39
  • @Michael I know, I just tried all possibilities to present message format, that's all ,once I figure out how to present message, I will delete one of them – O user Feb 11 '16 at 02:43
  • So if you cut it down to one, then I assume you will present one from `tapOnEmergency`. And then you want to present another immediately from within that one? You could do that in `viewDidLoad`. It would help if you described what you want to happen in terms of the flow of processes. – Michael Feb 11 '16 at 02:48
  • I only just saw your comment "note that emergency has no scene/view". This is not good - it inherits from `UIViewController`, so it has a view whether or not you want it. It sounds to me like you want a generic class to handle your text messages. In that case, inherit from `NSObject` rather than `UIViewController`. – Michael Feb 11 '16 at 02:50
  • @Michael the problem is message code is written in emergency class and its function name is "emergencyMessage", I try to invoke this function in MainMenu class, but I can't, as Xcode says ` Attempt to present on whose view is not in the window hierarchy! ` hopefully this explains my problem to ya – O user Feb 11 '16 at 02:56
  • because I wrote presentViewController in emergencyMessage function and it's only available in UIViewController class – O user Feb 11 '16 at 02:57
  • Did you see my comment about emergency having a view? Why does it inherit from UIViewController if it's not supposed to have a view? That's why you're getting an error - the Emergency view is trying to present and you're asking it to present MFMessageCompose – Michael Feb 11 '16 at 02:58
  • and I answered to your question and I said because I wrote presentViewController in emergencyMessage function which it's only available in UIViewController class, if I remove UIViewController, an error will appear and tells me to remove presentViewController – O user Feb 11 '16 at 03:01

1 Answers1

1

The Emergency class should not inherit from UIViewController since it is not a view controller and does not manage a view. However, it needs to be able to present a view controller itself, so it needs to be passed in one. Therefore your MainMenu becomes:

class MainMenu: UIViewController {
    let getHelp:Emergency = Emergency()
    @IBAction func TapOnEmergency(sender: UIButton) {
        getHelp.emergencyMessage(self)
    }
}

And the Emergency class becomes:

class Emergency: NSObject, MFMessageComposeViewControllerDelegate {
    func emergencyMessage(vc: UIViewController)
    {
         let textMessageRecipients = [number!]
         if (MFMessageComposeViewController.canSendText() ) {
             messageComposer.recipients = textMessageRecipients
             messageComposer.body = ""
             messageComposer.messageComposeDelegate = self
             vc.presentViewController(messageComposer, animated: false,completion: nil)
         } else {
             let errorAlert = UIAlertController(title: "Cannot Send Text Message", message: "Your device is not able to send text messages.",                 preferredStyle: UIAlertControllerStyle.Alert)
             errorAlert.addAction(UIAlertAction(title: "OK", style:  UIAlertActionStyle.Cancel, handler: nil))
            vc.presentViewController(errorAlert, animated: true, completion: nil)
         }
    }
}
Michael
  • 8,891
  • 3
  • 29
  • 42
  • after I tried your solution, all errors are gone, but it's telling ` Remote compose controller timed out (YES)! ` and takes too long to preform, but all errors are gone – O user Feb 11 '16 at 08:48
  • now the code it works just fine, just one problem I can't dismiss view :P I know how I can do in traditional way `func messageComposeViewController(controller: MFMessageComposeViewController, didFinishWithResult result: MessageComposeResult) { dismissViewControllerAnimated(true, completion: nil) switch (result.rawValue) { case MessageComposeResultSent.rawValue: print("Message sent success") default: return } }` but this situation I don't know how – O user Feb 11 '16 at 09:11
  • I assume you've implemented `- messageComposeViewController:didFinishWithResult`, so you could dismiss it there. – Michael Feb 11 '16 at 22:35
  • yeah I did, ` messageComposer.dismissViewControllerAnimated(true, completion: nil) `, this code of line has solved the problem, thanks a lot Michael – O user Feb 12 '16 at 22:33