Reputation: 15
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.
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
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:
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
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
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