GagaBytes
GagaBytes

Reputation: 15

Swift - Using UITableViewController to create sub-menus

I am developing a simple hybrid iOS app using Xcode 7 and Swift 2. I need to create submenus from my main menu.

My main menu uses a table view. Now I can create a second UITableViewController and load the sub menu within that and create a third UITableViewController to load another sub menu and so on.

But is there a better way by reusing my initial UITableViewController?

UITableViewController is embedded in a UINavigationController.

And I am using a single UIViewController to show the final textual information.

enter image description here

Here is my Main Menu code:

class MainMenuTableViewController: UITableViewController {

// MARK: Properties

var mainMenu = [MainMenu]()
var Item1Menu = [MainMenu]()
var Item12Menu = [MainMenu]()
var selectedMenu: Int = 0

override func viewDidLoad() {
    super.viewDidLoad()

    // Load the sample data.
    loadMainMenu()
    loadItem1Menu()
    loadItem12Menu()

}

func loadMainMenu() {
    let image1 = UIImage(named: "menu-1")!
    let menuItem1 = MainMenu(name: "Item 1", photo: image1, url: "no-url", urlType: "subMenu")!

    let image2 = UIImage(named: "menu-2")!
    let menuItem2 = MainMenu(name: "Item 2", photo: image2, url: "our-services", urlType: "localURL")!

    let image3 = UIImage(named: "menu-3")!
    let menuItem3 = MainMenu(name: "Item 3", photo: image3, url: "http://www.google.com", urlType: "webURL")!

    let image4 = UIImage(named: "menu-1")!
    let menuItem4 = MainMenu(name: "Item 4", photo: image4, url: "our-info", urlType: "localURL")!

    let image5 = UIImage(named: "menu-2")!
    let menuItem5 = MainMenu(name: "Item 5", photo: image5, url: "http://www.bing.com", urlType: "webURL")!

    //mainMenu.removeAll()
    mainMenu += [menuItem1, menuItem2, menuItem3, menuItem4, menuItem5]
}

func loadItem1Menu() {
    let image = UIImage(named: "menu-1")!
    let menuItem1 = MainMenu(name: "Item 1.1", photo: image, url: "our-profile", urlType: "localURL")!

    let menuItem2 = MainMenu(name: "Item 1.2", photo: image, url: "no-url", urlType: "sub-menu")!

    let menuItem3 = MainMenu(name: "Item 1.3", photo: image, url: "our-history", urlType: "localURL")!

    //mainMenu.removeAll()
    Item1Menu += [menuItem1, menuItem2, menuItem3]
}

func loadItem12Menu() {
    let image = UIImage(named: "menu-1")!
    let menuItem1 = MainMenu(name: "Item 1.2.1", photo: image, url: "portfolio-1", urlType: "localURL")!

    let menuItem2 = MainMenu(name: "Item 1.2.2", photo: image, url: "portfolio-2", urlType: "localURL")!

    let menuItem3 = MainMenu(name: "Item 1.2.3", photo: image, url: "portfolio-3", urlType: "localURL")!

    //mainMenu.removeAll()
    Item12Menu += [menuItem1, menuItem2, menuItem3]
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return mainMenu.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Table view cells are reused and should be dequeued using a cell identifier.
    let cellIdentifier = "MainMenuTableViewCell"
    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MainMenuTableViewCell

    // Fetches the appropriate menu for the data source layout.
    let menu = mainMenu[indexPath.row]

    cell.nameLabel.text = menu.name
    cell.menuImageView.image = menu.photo

    return cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    var segueString:String
    selectedMenu = indexPath.row
    let urlType = mainMenu[selectedMenu].urlType

    if urlType == "subMenu" {

        //http://stackoverflow.com/a/38763630/1019454
        let vc = (UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())).instantiateViewControllerWithIdentifier("MenuViewController") as! MainMenuTableViewController

        vc.mainMenu = Item1Menu
        // then push or present view controller
        self.navigationController!.pushViewController(vc, animated: true)

    } else {


        switch(mainMenu[selectedMenu].urlType){

        case "localURL":
            segueString = "ShowLocalWeb"
        default:
            segueString = "ShowWeb"
        }

        self.performSegueWithIdentifier(segueString, sender: self)
    }
}


// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    /*
    if segue.identifier == "ShowSubMenu" {
        let subMenuController = segue.destinationViewController as! SubMenuTableViewController
        subMenuController.subMenu = mainMenu[selectedMenu]
    }*/

    if segue.identifier == "ShowLocalWeb" {
        let localViewController = segue.destinationViewController as! LocalWebViewController
        localViewController.mainMenu = mainMenu[selectedMenu]
    }

    if segue.identifier == "ShowWeb" {
        let webViewController = segue.destinationViewController as! WebViewController
        webViewController.mainMenu = mainMenu[selectedMenu]

    }
}

}

Upvotes: 1

Views: 2336

Answers (3)

Vivek Molkar
Vivek Molkar

Reputation: 3960

Actually you are all set to go. The only change you need is create an instance of MainMenuTableViewController and assign mainMenu with your new menu.

Example:

When you wish to show new menu.

let vc = MainMenuTableViewController()
vc.menu = <new menu here>
// then push or present view controller
self.navigationController.pushViewController(vc, animated: true)

Response to Comment below:

No, you dont have to create new file, but new instance of MainMenuTableViewController. You have to change the data part, in your case array that contains menu. <new menu here> refers to array of new menu items.

For this you have to Decouple the data, which will be helpful.

Edit:

Instead of creating your vc in the above fashion you can try creating it from the storyboard. Please follow the steps:

  1. In storyboard assign storyboard identifier to MainMenuTableViewController and instead of this line

let vc = MainMenuTableViewController()

use

let vc = (UIStoryboard(name: <your storyboard file name>, bundle: NSBundle.mainBundle())).instantiateViewControllerWithIdentifier(<storyboard identifier of MainMainMenuTableViewController>)

The reason I suspect is the line that i previously is unable find cell to create and hence crasing.

Upvotes: 1

Andrzej Filipowicz
Andrzej Filipowicz

Reputation: 248

If you want an easiest solution you should switch your datasource and call .reloadData() on the tableView.

Whether you will actually have a few objects which implement the datasource protocol and just switch between them or have an array of objects acting as your datasource and just switch content of this array is your decision and is more of a styling / architectural thing.

Upvotes: 0

anaghaajith27
anaghaajith27

Reputation: 61

If my understanding of the question is right, I'm guessing you have a main menu and want to show submenus underneath them.

One way of doing this is by inserting and deleting rows. This way you can just reuse the same UITableViewController. So, on click of Item 2 a set of rows can be inserted to the tableView at that index populated with your submenu data.

You can use the functions insertRowsAtIndexPaths(:withRowAnimation:) and deleteRowsAtIndexPaths(:withRowAnimation:) inside a block of call to tableView.beginUpdates() and tableView.endUpdates() and update the tableView datasource to achieve this.

Hope this helps.

Upvotes: 0

Related Questions