Is there any way to create a custom dropdown in Swift? - ios

This is the dropdown menu I want to create:
This is how my textfield should look after the item from drop down is selected:
I have tried using https://github.com/AssistoLab/DropDown this to achieve the drop down but it seems only registers a single xib.
I tried registering multiple xibs and working with it but didn't work.
I am still stuck at the dropdown part and havent got to part after slection of menu but tried using https://github.com/ElaWorkshop/TagListView to achieve the post selection part but failed.
class ViewController: UIViewController {
#IBOutlet weak var showlabel: UILabel!
#IBAction func action(_ sender: UIButton) {
chooseArticleDropDown.show()
}
let chooseArticleDropDown = DropDown()
override func viewDidLoad() {
super.viewDidLoad()
setupChooseArticleDropDown()
customizeDropDown(chooseArticleDropDown)
// Do any additional setup after loading the view.
}
func customizeDropDown(_ sender: AnyObject) {
/*** FOR CUSTOM CELLS ***/
chooseArticleDropDown.cellNib = UINib(nibName: "MyCell", bundle: nil)
chooseArticleDropDown.cellNib = UINib(nibName: "MyCell2", bundle: nil)
chooseArticleDropDown.customCellConfiguration = { (index: Index, item: String, cell: DropDownCell) -> Void in
if index % 2 == 0 {
guard let cell = cell as? MyCell else { return }
cell.optionLabel.text = item
// Setup your custom UI components
cell.logoImageView.image = UIImage(named: "logo_\(index % 10)")
}else{
guard let cell = cell as? MyCell2 else { return }
cell.optionLabel.text = item
// Setup your custom UI components
cell.lblr.text = item
cell.logoImageView.image = UIImage(named: "logo_\(index % 10)")
}
}
}
func setupChooseArticleDropDown() {
chooseArticleDropDown.anchorView = showlabel
chooseArticleDropDown.dataSource = [
"iPhone SE | Black | 64G",
"Samsung S7",
"Huawei P8 Lite Smartphone 4G",
"Asus Zenfone Max 4G",
"Apple Watwh | Sport Edition"
]
// Action triggered on selection
chooseArticleDropDown.selectionAction = { [weak self] (index, item) in
self?.showlabel.text = item
}
}
}
This code is what I tried to acive the different dropdown item view.

Related

Activating a search controller whose navigation item is not at the top of the stack | Swift

The error:
[Assert] Surprise! Activating a search controller whose navigation item is not at the top of the stack. This case needs examination in UIKit. items = (null),
search hosting item = <UINavigationItem: 0x1068473a0> title='PARTS' style=navigator leftBarButtonItems=0x282bfb8d0 rightBarButtonItems=0x282bfb890 searchController=0x110024400 hidesSearchBarWhenScrolling
Why am I getting this error and how do I fix it? This question is similar to another post, but there was only one response to it and the response was not detailed at all (therefore not helpful).
import UIKit
import SPStorkController
struct Part {
var title: String?
var location: String?
var selected: Bool? = false
}
class InspectorViewController: UIViewController, UINavigationControllerDelegate, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating, UISearchBarDelegate {
private let initials = InspectorPartsList.getInitials() // model
private var parts = InspectorPartsList.getDamageUnrelatedParts() // model
var filteredParts: [Part] = [] // model
var searching = false
var searchController = UISearchController(searchResultsController: nil)
lazy var searchBar: UISearchBar = UISearchBar()
var isSearchBarEmpty: Bool {
return searchController.searchBar.text?.isEmpty ?? true
}
var navBar = UINavigationBar()
let inspectorTableView = UITableView() // tableView
var darkTheme = Bool()
override func viewDidLoad() {
super.viewDidLoad()
// setup the navigation bar
setupNavBar()
// add the table view
setupInspectorTableView()
// add the search controller to the navigation bar
setupSearchController()
}
func setupNavBar() {
navBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 100))
view.addSubview(navBar)
let navItem = UINavigationItem(title: "PARTS")
let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(self.addBtnTapped))
let cancelItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: nil, action: #selector(self.cancelBtnTapped))
navItem.rightBarButtonItem = doneItem
navItem.leftBarButtonItem = cancelItem
navItem.searchController = searchController
navBar.setItems([navItem], animated: false)
}
#objc func cancelBtnTapped() {
// dismiss the storkView
SPStorkController.dismissWithConfirmation(controller: self, completion: nil)
}
#objc func addBtnTapped() {
// get all of the selected rows
// Update the InspectionData model with the selected items... this will allow us to update the InspectionTableView in the other view
// create an empty array for the selected parts
var selectedParts = [Part]()
// loop through every selected index and append it to the selectedParts array
for part in parts {
if part.selected! {
selectedParts.append(part)
}
}
// update the InspectionData model
if !selectedParts.isEmpty { // not empty
InspectionData.sharedInstance.partsData?.append(contentsOf: selectedParts)
// update the inspectionTableView
updateInspectionTableView()
}
// dismiss the storkView
SPStorkController.dismissWithConfirmation(controller: self, completion: nil)
}
func cancelAddPart() {
// dismiss the storkView
SPStorkController.dismissWithConfirmation(controller: self, completion: nil)
}
private func setupInspectorTableView() {
// set the data source
inspectorTableView.dataSource = self
// set the delegate
inspectorTableView.delegate = self
// add tableview to main view
view.addSubview(inspectorTableView)
// set constraints for tableview
inspectorTableView.translatesAutoresizingMaskIntoConstraints = false
// inspectorTableView.topAnchor.constraint(equalTo: fakeNavBar.bottomAnchor).isActive = true
inspectorTableView.topAnchor.constraint(equalTo: navBar.bottomAnchor).isActive = true
inspectorTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
inspectorTableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
inspectorTableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
// allow multiple selection
inspectorTableView.allowsMultipleSelection = true
inspectorTableView.allowsMultipleSelectionDuringEditing = true
// register the inspectorCell
inspectorTableView.register(CheckableTableViewCell.self, forCellReuseIdentifier: "inspectorCell")
}
func setupSearchController() {
// add the bar
searchController.searchResultsUpdater = self
searchController.searchBar.delegate = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search by part name or location"
definesPresentationContext = true
searchController.searchBar.sizeToFit()
self.inspectorTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return filteredParts.count
} else {
return parts.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let inspectorCell = tableView.dequeueReusableCell(withIdentifier: "inspectorCell", for: indexPath)
var content = inspectorCell.defaultContentConfiguration()
var part = Part()
if searching {
// showing the filteredParts array
part = filteredParts[indexPath.row]
if filteredParts[indexPath.row].selected! {
// selected - show checkmark
inspectorCell.accessoryType = .checkmark
} else {
// not selected
inspectorCell.accessoryType = .none
}
} else {
// showing the parts array
part = parts[indexPath.row]
if part.selected! {
// cell selected - show checkmark
inspectorCell.accessoryType = .checkmark
} else {
// not selected
inspectorCell.accessoryType = .none
}
}
content.text = part.title
content.secondaryText = part.location
inspectorCell.contentConfiguration = content
return inspectorCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Note: When you select or unselect a part in the filteredParts array, you must also do so in the parts array
if searching { // using filteredParts array
if filteredParts[indexPath.row].selected! { // selected
filteredParts[indexPath.row].selected = false // unselect the part
// search the parts array for the part by both the title and location, so we for sure get the correct part (there could be parts with identical titles with different locations)
if let part = parts.enumerated().first(where: { $0.element.title == filteredParts[indexPath.row].title && $0.element.location == filteredParts[indexPath.row].location}) { // exact part (with same title & location) found
parts[part.offset].selected = false // unselect the part
}
} else { // not selected
filteredParts[indexPath.row].selected = true // select the part
if let part = parts.enumerated().first(where: { $0.element.title == filteredParts[indexPath.row].title && $0.element.location == filteredParts[indexPath.row].location}) { // exact part (with same title & location) found
parts[part.offset].selected = true // select the part
}
}
} else { // using parts array
if parts[indexPath.row].selected! { // selected
parts[indexPath.row].selected = false // unselect the part
} else { // not selected
parts[indexPath.row].selected = true // select the part
}
}
inspectorTableView.reloadRows(at: [indexPath], with: .none) // reload the tableView
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredParts = parts.filter { ($0.title?.lowercased().prefix(searchText.count))! == searchText.lowercased() }
searching = true
inspectorTableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
inspectorTableView.reloadData()
}
func updateSearchResults(for searchController: UISearchController) {
}
private func updateInspectionTableView() {
NotificationCenter.default.post(name: NSNotification.Name("updateInspectionTable"), object: nil)
}
}
// CHECKABLE UITABLEVIEWCELL
class CheckableTableViewCell: UITableViewCell {
}

Interaction between DUXPreFlightStatusWidget and DUXPreflightChecklistController is not working as advertised

According to https://developer.dji.com/api-reference/ios-uilib-api/Widgets/PreFlightStatusWidget.html:
"Tapping on status text will toggle between show and hide DUXPreflightChecklistController."
When I tap on the status text in the widget, the DUXPreflightChecklistController is not shown. Also, if I manually show the DUXPreflightChecklistController, there is a close button in the top right corner of the panel but tapping it does not hide the panel.
What is the proper way to configure this panel?
I'm using DJISDK 4.7.1 and DJIUXSDK 4.7.1 with Swift and iOS 12/xCode 10.0.
To provide a bit more detail, I do not want to use the Default Layout but I am using DUXStatusBarViewController. That is embedded in a UIView across the top of my app. I cannot find any properties for that controller that would allow me to hook it up to my instance of DUXPreflightChecklistController, which is also embedded in a UIView.
For: DUXPreflightChecklistController
I'd just solved that
var preflightChecklistController: DUXPreflightChecklistController!
weak var preFlightTableView: UITableView!
private var compassItemIndex: Int = -1
private var storageItemIndex: Int = -1
override func viewDidLoad() {
super.viewDidLoad()
preflightChecklistController = DUXPreflightChecklistController()
addChild(preflightChecklistController)
}
func renderChecklist() {
if let checklistVC = preflightChecklistController {
for subview in checklistVC.view.subviews {
if subview.isKind(of: UITableView.self) {
if let tableView = subview as? UITableView {
self.view.addSubview(tableView)
preFlightTableView = tableView
}
}
}
guard let checklistManager = checklistVC.checklistManager else { return }
let itemList = checklistManager.preFlightChecklistItems
for (index, item) in itemList.enumerated() {
if let _ = item as? DUXStorageCapacityChecklistItem {
storageItemIndex = index
}
if let _ = item as? DUXCompassChecklistItem {
compassItemIndex = index
}
}
preFlightTableView.reloadData()
checklistManager.startCheckingList()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
renderChecklist()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard preFlightTableView != nil else { return }
if let compassCell = preFlightTableView.cellForRow(at: IndexPath(item: compassItemIndex, section: 0)) {
for view in compassCell.subviews {
if let button = view as? UIButton, button.titleLabel?.text == "Calibrate" {
button.addTarget(self, action: #selector(doActionForSpecifiedBTN(sender:)), for: .touchUpInside)
break
}
}
}
if let storageCell = preFlightTableView.cellForRow(at: IndexPath(item: storageItemIndex, section: 0)) {
for view in storageCell.subviews {
if let button = view as? UIButton, button.titleLabel?.text == "Format" {
button.addTarget(self, action: #selector(doActionForSpecifiedBTN(sender:)), for: .touchUpInside)
break
}
}
}
}
#objc func doActionForSpecifiedBTN(sender: UIButton) {
guard let btnTitle = sender.titleLabel else { return }
switch btnTitle.text {
case "Calibrate":
// your func goes here
case "Format":
// your func goes here
default:
break
}
}

UITextField doesn't end editing in a UITableViewCell in Swift 4

I am still new to swift and I would ask you for advice. Thank you in advance and sorry for my bad English.
My goal is:
User tap edit button in the table's row. UITextField appears instead cell. After entering value and pressing Return key UITextField disappears again and cell is recalculated.
editButton pressed -> hide priceCell & show UITextField & show keyboard & start editing/entering value (blinking cursor) -> stop editing/entering value execute by pressing Return key -> hide UITextField & shows priceCell & save entered value into array & reload edited row
I use this answer as starting blueprint.
I would like to also use .decimalPad keyboard to easier entering numeric value and limit user to use only numbers (and decimal point), but this exclude use Return key as stop editing, am I right?
I found this possible solution, but it seems to me complex for my problem...
my ViewController:
import UIKit
class PortfolioViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, PortfolioCellDelegate {
let getData = GetData()
...
override func viewDidLoad() {
super.viewDidLoad()
cellTableView.delegate = self
cellTableView.dataSource = self
cellTableView.register(UINib(nibName: "PortfolioCell", bundle: nil), forCellReuseIdentifier: "portfolioCell")
self.currencyControl.selectedSegmentIndex = MyVariables.currencyControlSelected
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let coinCell = tableView.dequeueReusableCell(withIdentifier: "portfolioCell", for: indexPath) as! PortfolioCell
...
coinCell.delegate = self
return coinCell
}
...
func portfolioButtonPressed(coinCell: PortfolioCell) {
let indexPath = self.cellTableView.indexPathForRow(at: coinCell.center)!
let selectedCell = cellTableView.cellForRow(at: indexPath) as! PortfolioCell
selectedCell.priceCell.isHidden = true
selectedCell.textCell.isHidden = false
selectedCell.textCell.delegate = self
func textFieldDidEndEditing(textField: UITextField) {
let owned: Double = Double(textField.text!)!
if owned >= 0 {
MyVariables.dataArray[indexPath.row].ownedCell = owned
} else {
MyVariables.dataArray[indexPath.row].ownedCell = 0.00
}
selectedCell.priceCell.isHidden = false
selectedCell.textCell.isHidden = true
self.cellTableView.reloadData()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
selectedCell.textCell.resignFirstResponder()
return true
}
}
...
}
my custom cell:
import UIKit
protocol PortfolioCellDelegate {
func portfolioButtonPressed(coinCell: PortfolioCell)
}
class PortfolioCell: UITableViewCell {
var delegate: PortfolioCellDelegate?
...
#IBAction func editCellPressed(_ sender: UIButton) {
delegate?.portfolioButtonPressed(coinCell: self)
}
...
}
For now when button is pressed proper UITextField shows, but don't dismiss after Return key is pressed.
Or should I change it completely and use tap gestures?
To end editing in any kind of scrollView, simply use this
cellTableView.keyboardDismissMode = .onDrag
or
cellTableView.keyboardDismissMode = .interactive
It will hide keyboard when you interact with the tableView
For number keypad you can add toolbar as a textField's inputAccessoryView. On toolbar add cancel button to dismiss keyboard.
There is two way to go:
1.) Delegate
2.) IQKeyboardManager
1.)
Use UITextFieldDelegate
There is one particular callback named "textFieldShouldEndEditing"
In this method, return true.
2.)
User the IQKeyboardManager one liner library. This library manages all the TextFields and scrollviews automatically. You activate it with one line in AppDelegate so it's easy to use.
https://github.com/hackiftekhar/IQKeyboardManager
Working but not as sleek as want it to be and also I was not capable to make IQKeyboardManager works so I did use inputAccessoryView.
custom cell:
import UIKit
protocol PortfolioCellDelegate {
func portfolioButtonPressed(didSelect coinCell: PortfolioCell)
func portfolioButtonPressed(coinCell:PortfolioCell, editingChangedInTextCell newValue:String)
}
class PortfolioCell: UITableViewCell, UITextFieldDelegate {
var delegate: PortfolioCellDelegate?
...
#IBAction func editCellPressed(_ sender: UIButton) {
textCell.becomeFirstResponder()
delegate?.portfolioButtonPressed(didSelect: self)
}
#IBAction func textCellValueChanged(_ sender: UITextField) {
if (sender.text?.isEmpty)! {
delegate?.portfolioButtonPressed(coinCell: self, editingChangedInTextCell: "XXX")
} else {
let text = sender.text
delegate?.portfolioButtonPressed(coinCell: self, editingChangedInTextCell: text!)
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.textCell.delegate = self
let flexiableSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneButtonAction))
let toolBar:UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: 35))
toolBar.barTintColor = UIColor(red:0.15, green:0.69, blue:0.75, alpha:1.0)
toolBar.tintColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0)
toolBar.setItems([flexiableSpace, doneButton], animated: false)
textCell.inputAccessoryView = toolBar
textCell.keyboardType = UIKeyboardType.decimalPad
}
#objc func doneButtonAction() {
textCell.endEditing(true)
}
...
}
ViewController:
import UIKit
class PortfolioViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, PortfolioCellDelegate {
let getData = GetData()
...
override func viewDidLoad() {
super.viewDidLoad()
cellTableView.delegate = self
cellTableView.dataSource = self
cellTableView.register(UINib(nibName: "PortfolioCell", bundle: nil), forCellReuseIdentifier: "portfolioCell")
self.currencyControl.selectedSegmentIndex = MyVariables.currencyControlSelected
getData.delegate = self
timeStampLabel.text = MyVariables.timeStamp
}
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.cellTableView.reloadData()
self.currencyControl.selectedSegmentIndex = MyVariables.currencyControlSelected
self.timeStampLabel.text = MyVariables.timeStamp
}
//MARK: - tableView
/***************************************************************/
...
func portfolioButtonPressed(coinCell: PortfolioCell, editingChangedInTextCell newValue: String) {
let indexPath = self.cellTableView.indexPathForRow(at: coinCell.center)!
let selectedCell = cellTableView.cellForRow(at: indexPath) as! PortfolioCell
selectedCell.priceCell.isHidden = false
selectedCell.textCell.isHidden = true
if newValue != "XXX" {
let owned: Double = Double(newValue)!
MyVariables.dataArray[indexPath.row].ownedCell = owned
}
selectedCell.priceCell.isHidden = false
selectedCell.textCell.isHidden = true
self.cellTableView.reloadRows(at: [indexPath], with: .automatic)
}
func portfolioButtonPressed(didSelect coinCell: PortfolioCell) {
let indexPath = self.cellTableView.indexPathForRow(at: coinCell.center)!
let selectedCell = cellTableView.cellForRow(at: indexPath) as! PortfolioCell
selectedCell.priceCell.isHidden = true
selectedCell.textCell.isHidden = false
}
...
}
It's easy: You should select that table view cell, then enable User Interaction Enabled in the attribute inspector.

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.
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]
}
}
}
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:
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.
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.
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.

ViewWillDisappear not getting called searchcontroller

When I'm in the middle of a search and then switch UItabs, ViewWillDisappear does not get called. Any idea as to why ViewWillDisappear does not get called when I have filtered results displaying and switch tabs?
func updateSearchResultsForSearchController(searchController: UISearchController) {
if self.searchController?.searchBar.text.lengthOfBytesUsingEncoding(NSUTF32StringEncoding) > 0 {
if let results = self.results {
results.removeAllObjects()
} else {
results = NSMutableArray(capacity: MyVariables.dictionary.keys.array.count)
}
let searchBarText = self.searchController!.searchBar.text
let predicate = NSPredicate(block: { (city: AnyObject!, b: [NSObject : AnyObject]!) -> Bool in
var range: NSRange = NSMakeRange(0, 0)
if city is NSString {
range = city.rangeOfString(searchBarText, options: NSStringCompareOptions.CaseInsensitiveSearch)
}
return range.location != NSNotFound
})
// Get results from predicate and add them to the appropriate array.
let filteredArray = (MyVariables.dictionary.keys.array as NSArray).filteredArrayUsingPredicate(predicate)
self.results?.addObjectsFromArray(filteredArray)
// Reload a table with results.
self.searchResultsController?.tableView.reloadData()
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(self.identifier) as! UITableViewCell
var text: String?
var imgtext:AnyObject?
if tableView == self.searchResultsController?.tableView {
if let results = self.results {
text = self.results!.objectAtIndex(indexPath.row) as? String
imgtext = MyVariables.dictionary[text!]
let decodedData = NSData(base64EncodedString: imgtext! as! String, options: NSDataBase64DecodingOptions(rawValue: 0) )
var decodedimage = UIImage(data: decodedData!)
cell.imageView?.image = decodedimage
}
} else {
text = MyVariables.dictionary.keys.array[indexPath.row] as String
}
cell.textLabel!.text = text
return cell
}
On the Load
override func viewDidLoad() {
super.viewDidLoad()
let resultsTableView = UITableView(frame: self.tableView.frame)
self.searchResultsController = UITableViewController()
self.searchResultsController?.tableView = resultsTableView
self.searchResultsController?.tableView.dataSource = self
self.searchResultsController?.tableView.delegate = self
// Register cell class for the identifier.
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: self.identifier)
self.searchResultsController?.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: self.identifier)
self.searchController = UISearchController(searchResultsController: self.searchResultsController!)
self.searchController?.searchResultsUpdater = self
self.searchController?.delegate = self
self.searchController?.searchBar.sizeToFit()
self.searchController?.hidesNavigationBarDuringPresentation = false;
self.tableView.tableHeaderView = self.searchController?.searchBar
self.definesPresentationContext = true
}
Had the same issue. viewWillDisappear is not called on the UITableViewController, but it is called in the UISearchController.
So I subclassed UISearchController and overrode the viewWillDisappear method. In my case I just needed to deactivate the search controller.
class SearchController: UISearchController {
override func viewWillDisappear(_ animated: Bool) {
// to avoid black screen when switching tabs while searching
isActive = false
}
}
Similar to #user5130344 I found that subclassing resolved my issue, although I found that isActive = false cleared the search bar where I wanted the search query to remain on returning to the view.
Here's my subclass instead - this fixed my issue with iOS 13 dismissing the parent view:
class MySearchController: UISearchController {
override func viewWillDisappear(_ animated: Bool) {
// to avoid black screen when switching tabs while searching
self.dismiss(animated: true)
}
}
I think its the problem with the xcode . Try to close it and reopen the project once again and try to run again

Resources