almiteyG almiteyG - 3 months ago 20
iOS Question

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]

}
}


}

Answer

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.

Comments