Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Presenting view controllers on detached view controllers

I have sideViewController with a button and Action, which present new view controller by clicking this button.

class sideViewController: UIViewController {
    @IBOutlet var buttonVC1 : UIButton!
    @IBAction func goToVC1 () {
        var VC1 = self.storyboard.instantiateViewControllerWithIdentifier("ViewController") as ViewController
        presentViewController(VC1, animated:true, completion: nil)
    }
}

I use this in main view controller:

class ViewController: UIViewController {
    var menu : sideViewController!
    override func viewDidLoad() {
        super.viewDidLoad()
        menu = self.storyboard.instantiateViewControllerWithIdentifier("menu") as      sideViewController
        menu.view.frame = CGRect(x: 0, y: 0, width: 160, height: 480)
        view.addSubview(menu.view)
}

when I click this button, the problem is: "Presenting view controllers on detached view controllers is discouraged"

What should I do to fix this?

like image 760
Yury Alexandrov Avatar asked Aug 20 '14 09:08

Yury Alexandrov


1 Answers

Problem

iOS is complaining that some other view(the detached view) which came after the main view is presenting something. It can present it, which it does apparently, but it's discouraged as it's not a good practice to do so.

Solution

Delegate/protocol pattern is suitable to solve this issue. By using this pattern, the action will be triggered inside the SideVC although this trigger will be sent to the MainVC and be performed there.

Therefore, since the action will be triggered by the MainVC, from iOS's perspective, it will all be safe and sound.

Code

SideVC:

protocol SideVCDelegate: class {
  func sideVCGoToVC1()
}

class sideVC: UIViewController {
  weak var delegate: SideVCDelegate?

  @IBOutlet var buttonVC1: UIButton!

  @IBAction func goToVC1 () {
    delegate.sideVCGoToVC1()
  }

MainVC

class MainVC: UIViewController, SideVCDelegate {
  var menu: sideVC!

  override func viewDidLoad() {
    super.viewDidLoad()
    menu = self.storyboard?.instantiateViewControllerWithIdentifier("menu") as sideViewController
    menu.delegate = self
    menu.view.frame = CGRect(x: 0, y: 0, width: 160, height: 480)
    view.addSubview(menu.view)
  }

  // MARK: - SideViewControllerDelegate
  func sideViewControllerGoToVC1() {
    menu.view.removeFromSuperview()
    var VC1 = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as ViewController
    presentViewController(VC1, animated:true, completion: nil)
  }
}

Note

Apart from the question you've asked, the below lines seems somewhat vague.

var VC1 = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as ViewController
menu.view.frame = CGRect(x: 0, y: 0, width: 160, height: 480)

You're obtaining a view controller from your storyboard which has a frame when you designed it inside Interface Builder but you're changing it afterwards. It's not a good practice to play with the frames of views once they're created.

Maybe you've intended to do something else but most likely, it's a problematic piece of code.

like image 63
Ron Fessler Avatar answered Oct 06 '22 00:10

Ron Fessler