1

I have an application with sideBarMenu which has five sections. In my storyboard I've created start MainViewController embedded in NavigationController. Then I've created same five VC's and again embed them in NavigationController. So I have 6 VC's, each of which is wrapped in its own NavigationController.

Each VC implements sideBarDelegate with function that has an index of selected menu.

Here is the code:

// SideBarTableViewController

protocol SideBarTableViewControllerDelegate {
    func SideBarControlDidSelectRow(indexPath: NSIndexPath)
}

class SideBarTableViewController: UITableViewController {

// ...

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: false)
        println(indexPath.row)
        delegate?.SideBarControlDidSelectRow(indexPath)
    }
}


// SideBar class ------------------------------------------------

@objc protocol SideBarDelegate {
    func SideBarDidSelectButtonAtIndex(index: Int)
    optional func SideBarWillClose()
    optional func SideBarWillOpen()
}

class SideBar: NSObject, SideBarTableViewControllerDelegate {

// ...

    func SideBarControlDidSelectRow(indexPath: NSIndexPath) {
        println(indexPath.row)
        delegate!.SideBarDidSelectButtonAtIndex(indexPath.row)
    }
}

Then in this function I want to present needed ViewController:

func SideBarDidSelectButtonAtIndex(index: Int) {
    presentViewControllerByIndex(index)
}

func presentViewControllerByIndex(index: Int) {
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    switch index {
    case 0:
        var viewController = storyBoard.instantiateViewControllerWithIdentifier("SearchVC") as! SearchViewController
        viewController.delegate = self
        self.presentViewController(viewController, animated: false, completion: nil)
        break

    // the same code here for other 4 VC's with their StoryboardId's

    default: break
    } 
}

Then in presented view controller if user select another section in menu should I destroy this VC before presenting selected ViewController? Because when I run my application and started switching between controllers the application memory in xCode increases (screenshot).

When I saw that I've started googling and found this answer. So I have created a protocol in my first menu VC just for test.

protocol myProtocol {
    func dissmissAndPresend(index: Int) -> Void
}

And when I need to present new VC I just call:

self.delegate?.dissmissAndPresend(index)

Then in my MainVC I implement this protocol and trying to dismiss previous VC and present the new one:

class MainViewController: UIViewController, SideBarDelegate, myProtocol {

func dissmissAndPresend(index: Int) {
    self.dismissViewControllerAnimated(false, completion: {
        self.presentViewControllerByIndex(index)
    })
}

Now when I launch my program and started to click on the first menu item it opens new VC but my memory increases as before. And also the navigationController for presented view has gone but in storyboard presented VC is embedded in navigationController.

What I am doing wrong? Can someone help me?

UPDATE::-------------------------------

Here is what I've tried:

class MainViewController: UIViewController, SideBarDelegate, searchVCProtocol {
    var searchVC: SearchViewController!
    var searchNavController: ShadowUINavigationController!

    override func viewDidLoad() {
        let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        searchVC = mainStoryboard.instantiateViewControllerWithIdentifier("SearchVC") as! SearchViewController
        searchVC.delegate = self
        searchNavController = ShadowUINavigationController(rootViewController: searchVC)
    }

    func SideBarDidSelectButtonAtIndex(index: Int) {
        switch index {
        case 0:
            println("asda")
            self.presentViewController(searchNavController, animated: false, completion: nil)
            break
        }
    }

Then it takes the user to SearchViewController and what if the user open menu again and click on SearchViewController again. How can I dismiss it and reopen. Here is what I've tried but it doesn't work:

In SeachViewController I've created a protocol:

protocol searchVCProtocol {
    func dismissAndPresent(index: Int) -> Void
}

Then I've added a variable for the delegate:

var delegate: searchVCProtocol?

Then when user selected menu item it fires this event:

func SideBarDidSelectButtonAtIndex(index: Int) {
    delegate?.dismissAndPresent(index)
}

And in MainViewController I've implemented this protocol and created dismissAndPresent method but I don't know how to restart presented viewController.

class MainViewController: UIViewController, SideBarDelegate, searchVCProtocol {
    func dismissAndPresent(index: Int) {
        // code to restart this VC
    }
}

What should I code for restarting presented VC?

Community
  • 1
  • 1
mkz
  • 2,302
  • 2
  • 30
  • 43

1 Answers1

1

You are calling instantiateViewControllerWithIdentifier every time, this creates ("instantiates") every time a new ViewController. Better would be to do this only once, keep a reference to it and then re-use it on demand.

Here how you can keep a reference. First you create a new variable on class level:

class MyClass {
    var viewController: SearchViewController!

Then, in viewDidLoad, you instantiate the view controller and assign it to the variable.

func viewDidLoad() {
    viewController = storyBoard.instantiateViewControllerWithIdentifier("SearchVC") as! SearchViewController
}

viewDidLoad is called only once so it will not happen anymore that you are creating multiple instances.

Then you can reuse this viewcontroller again and again:

func presentViewControllerByIndex(index: Int) {
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    switch index {
    case 0:
        // Here you can reuse the formerly created viewcontroller 
        viewController.delegate = self
        self.presentViewController(viewController, animated: false, completion: nil)
        break

    // the same code here for other 4 VC's with their StoryboardId's

    default: break
    } 
}
Darko
  • 9,655
  • 9
  • 36
  • 48
  • Please, can you give me an example how to keep a reference for instantiated viewController? – mkz Aug 03 '15 at 22:13
  • I have updated it. Please mark it as "Answer" if this answers your question. – Darko Aug 04 '15 at 07:40
  • I will try and reply later – mkz Aug 04 '15 at 08:46
  • Well, this is totally another question and should be posted as another question. Does the solution I proposed solved the memory leak? – Darko Aug 04 '15 at 09:38
  • As I see, it solved memory leak but now I'm confused how to restart viewController if needed or launch another selected menuVC because or this warning: `Warning: Attempt to present on whose view is not in the window hierarchy!` – mkz Aug 04 '15 at 10:06