Swift - 使用 UITableViewController 创建子菜单
Swift - Using UITableViewController to create sub-menus
我正在使用 Xcode 7 和 Swift 2 开发一个简单的混合 iOS 应用程序。我需要从主菜单创建子菜单。
我的主菜单使用 table 视图。现在我可以创建第二个 UITableViewController
并在其中加载子菜单,然后创建第三个 UITableViewController
以加载另一个子菜单,依此类推。
但是有没有更好的方法重新使用我的初始 UITableViewController
?
UITableViewController
嵌入在 UINavigationController
.
并且我使用单个 UIViewController
来显示最终的文本信息。
这是我的主菜单代码:
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" {
//
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]
}
}
}
如果您想要一个最简单的解决方案,您应该切换数据源并在 tableView 上调用 .reloadData()。
您是否真的有几个实现数据源协议的对象并只是在它们之间切换,或者有一个对象数组作为您的数据源并且只是切换这个数组的内容是您的决定并且更像是一种样式/建筑的东西。
如果我对这个问题的理解是正确的,我猜你有一个主菜单并且想在它们下面显示子菜单。
执行此操作的一种方法是插入和删除行。这样你就可以重用同一个 UITableViewController。因此,在单击项目 2 时,可以将一组行插入到填充有子菜单数据的索引处的 tableView 中。
您可以在 tableView.beginUpdates() 和 tableView.endUpdates() 并更新 tableView 数据源以实现此目的。
希望对您有所帮助。
实际上,您已经准备就绪。您需要做的唯一更改是创建一个 MainMenuTableViewController
的实例并为您的新菜单分配 mainMenu
。
示例:
当您希望显示新菜单时。
let vc = MainMenuTableViewController()
vc.menu = <new menu here>
// then push or present view controller
self.navigationController.pushViewController(vc, animated: true)
回复以下评论:
不,您不必创建新文件,而是 MainMenuTableViewController
的新实例。您必须更改数据部分,在您的案例数组中包含 menu
。 <new menu here>
指的是新菜单项数组。
为此,您必须 Decouple 数据,这将很有帮助。
编辑:
您可以尝试从情节提要中创建它,而不是以上述方式创建您的 vc
。请按照以下步骤操作:
- 在情节提要中,将情节提要标识符分配给
MainMenuTableViewController
而不是这一行
let vc = MainMenuTableViewController()
使用
let vc = (UIStoryboard(name: <your storyboard file name>, bundle: NSBundle.mainBundle())).instantiateViewControllerWithIdentifier(<storyboard identifier of MainMainMenuTableViewController>)
我怀疑的原因是我之前无法找到要创建的单元格的行,因此出现了错误。
我正在使用 Xcode 7 和 Swift 2 开发一个简单的混合 iOS 应用程序。我需要从主菜单创建子菜单。
我的主菜单使用 table 视图。现在我可以创建第二个 UITableViewController
并在其中加载子菜单,然后创建第三个 UITableViewController
以加载另一个子菜单,依此类推。
但是有没有更好的方法重新使用我的初始 UITableViewController
?
UITableViewController
嵌入在 UINavigationController
.
并且我使用单个 UIViewController
来显示最终的文本信息。
这是我的主菜单代码:
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" {
//
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]
}
}
}
如果您想要一个最简单的解决方案,您应该切换数据源并在 tableView 上调用 .reloadData()。
您是否真的有几个实现数据源协议的对象并只是在它们之间切换,或者有一个对象数组作为您的数据源并且只是切换这个数组的内容是您的决定并且更像是一种样式/建筑的东西。
如果我对这个问题的理解是正确的,我猜你有一个主菜单并且想在它们下面显示子菜单。
执行此操作的一种方法是插入和删除行。这样你就可以重用同一个 UITableViewController。因此,在单击项目 2 时,可以将一组行插入到填充有子菜单数据的索引处的 tableView 中。
您可以在 tableView.beginUpdates() 和 tableView.endUpdates() 并更新 tableView 数据源以实现此目的。
希望对您有所帮助。
实际上,您已经准备就绪。您需要做的唯一更改是创建一个 MainMenuTableViewController
的实例并为您的新菜单分配 mainMenu
。
示例:
当您希望显示新菜单时。
let vc = MainMenuTableViewController()
vc.menu = <new menu here>
// then push or present view controller
self.navigationController.pushViewController(vc, animated: true)
回复以下评论:
不,您不必创建新文件,而是 MainMenuTableViewController
的新实例。您必须更改数据部分,在您的案例数组中包含 menu
。 <new menu here>
指的是新菜单项数组。
为此,您必须 Decouple 数据,这将很有帮助。
编辑:
您可以尝试从情节提要中创建它,而不是以上述方式创建您的 vc
。请按照以下步骤操作:
- 在情节提要中,将情节提要标识符分配给
MainMenuTableViewController
而不是这一行
let vc = MainMenuTableViewController()
使用
let vc = (UIStoryboard(name: <your storyboard file name>, bundle: NSBundle.mainBundle())).instantiateViewControllerWithIdentifier(<storyboard identifier of MainMainMenuTableViewController>)
我怀疑的原因是我之前无法找到要创建的单元格的行,因此出现了错误。