Luiz Luiz - 2 months ago 23
Swift Question

Storyboard loading only once

Explanation



I'm trying to build a simple email code in separate swift files (in this case:
GameViewController.swift
and
MailViewController.swift
).

What should happen: I gotta touch the screen in
GameViewController
to call
MailViewController
, and when canceling or sending an email, it shall go back to
GameViewController
.

What is happening: It calls
MailViewController
and go back when touching
Cancel
or
Send
, but only once. When I try to do it again (even when closing and opening the app again) a black screen shows up when trying to get back to
GameViewController
.




Code



You can download the code below by clicking here.

GameViewController

import UIKit
import SpriteKit

class GameViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

// Set view size.
let scene = GameScene(size: view.bounds.size)

// Configure the view.
let skView = view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true

/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true

/* Set the scale mode to scale to fit the window */
scene.scaleMode = .ResizeFill

skView.presentScene(scene)

//Register mail observer (so I can call from GameScene)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.openMailViewController), name: "openMailViewController", object: nil)
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .Landscape
} else {
return .Landscape
}
}
}

extension GameViewController{

func openMailViewController(){
self.performSegueWithIdentifier("openMailViewController", sender: self)
}
}


MailViewController

import UIKit
import SpriteKit
import MessageUI

class MailViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

self.openMailController()
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}
}

//Mail
extension MailViewController: MFMailComposeViewControllerDelegate {

func openMailController() {

let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self //extremely important to set the mailComposeDelegate property, not the delegate property

self.presentViewController(mailComposerVC, animated: true, completion: nil)
}

func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {

//dismiss mail
self.dismissViewControllerAnimated(true, completion: nil)

//go back to the game
backToGameViewController()
}
}

extension MailViewController{

func backToGameViewController(){
self.performSegueWithIdentifier("backToGameViewController", sender: self)
}
}


Main.storyboard

enter image description here



Thanks in advance,

Luiz.

Answer

If you replace

self.performSegueWithIdentifier("backToGameViewController", sender: self)

with

self.dismissViewControllerAnimated(true, completion: nil)

your code will work, but I don't think it's actually what you want to do.

The reason this works is from your game controller you're presenting MailViewController, which is then presenting an MFMailComposeViewController. Since you're presenting two at once, you're getting an odd double animation where a blank view slides up before the mail view slides up. In order to fully dismiss the mail views then, you need to call dismissViewController twice.

A better approach would be to present the MFMailComposeController directly from GameController.

Comments