UITabBar disappears after "Back" button - swift

I have a UITableView with a TabBar .
When I click a cell it takes me to a new view, and when I click "Back"
I am back to the previous UITableView.
Only this time, the TabBar doesn't show. How can I make it appear again ?
Notice: The left-most view is the view shown when clicking a cell
View A and B
After clicking "Back" - UITabBar gone

If you set your "back" button manually, just set your "back" segue's destination from viewController to navigationController.
But the correct way to use TabBar and NavController is like this:
With this setup, it should work.
class ViewController: UIViewController {
var array = ["one", "two", "three"]
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = array[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToDetail", sender: self)
}
}
EDIT
Since you hide your tabBar in view B, you need just unhide it.
Add this code to your view B
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.tabBarController?.tabBar.isHidden = false
}

Related

Swift UITableview Reload Cell

I'm stuck with the following, any inputs would be highly appreciated.
My app has a UITableViewController with custom cells. Let's name its UITableView as TABLE VIEW-1. I am using XIB as its custom cell. Inside that xib, there is another UITableView, (TABLE VIEW-2), with another XIB as its custom cell.
My question is, How can I reload cells of (TABLE VIEW-2) from (TABLE VIEW-1) once I get data from an API in (TABLE VIEW-1). I want to use delegate and protocols to do this.
OR, What would be the correct way of performing this and how would I go about it?
Create a reference of TableView1 in the TableView2 ViewController. You can do this by
-- Open the Assistant Editor
-- Right-click and drag from your UI element (i.e. label) to the code file
-- Xcode auto inserts code for you to create the name and connection
Then call tableView2.reloadData(), where tableView2 is the name of the outlet you just created.
Create a reference of the TABLE VIEW-2 in the TABLE VIEW-1 custom cell (TABLE VIEW-1 CELL)
Create a method inside TABLE VIEW-1 CELL to reload its data alone with the TABLE VIEW-2 (Optional but useful to organize your code)
Inside the tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell of the TABLE VIEW-1 call reload function
class ViewController: UIViewController {
#IBOutlet weak var mainTable: UITableView!
let sampleData = [
(section: "News", SubSections: [
"Breaking news",
"Current Affairs",
"Local"
]) ]
override func viewDidLoad() {
super.viewDidLoad()
self.mainTable.estimatedRowHeight = 200
self.mainTable.rowHeight = UITableView.automaticDimension
let nib: UINib = UINib(nibName: String(describing: MainCell.self), bundle: Bundle.main)
self.mainTable.register(nib, forCellReuseIdentifier: String(describing: MainCell.self))
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
self.sampleData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: MainCell = tableView.dequeueReusableCell(withIdentifier: String(describing: MainCell.self), for: indexPath) as! MainCell
let sectionData = self.sampleData[indexPath.row]
cell.setUpData(title: sectionData.section, data: sectionData.SubSections)
return cell
}
}
class MainCell: UITableViewCell {
#IBOutlet weak var sectionTitle: UILabel!
#IBOutlet weak var internalTable: UITableView!
var tableData:[String]?
override func awakeFromNib() {
super.awakeFromNib()
self.internalTable.estimatedRowHeight = 200
self.internalTable.rowHeight = UITableView.automaticDimension
let nib: UINib = UINib(nibName: String(describing: InsideCell.self), bundle: Bundle.main)
self.internalTable.register(nib, forCellReuseIdentifier: String(describing: InsideCell.self))
}
func setUpData(title: String, data:[String]) {
self.sectionTitle.text = title
self.tableData = data
self.internalTable.reloadData()
}
}
extension MainCell: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
self.tableData?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: InsideCell = tableView.dequeueReusableCell(withIdentifier: String(describing: InsideCell.self), for: indexPath) as! InsideCell
if let subSectionData = self.tableData?[indexPath.row] {
cell.subSectionTitle.text = subSectionData
}
return cell
}
}
class InsideCell: UITableViewCell {
#IBOutlet weak var subSectionTitle: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}

Aftar i click on cell its pass me 2 views, how can i fix it?

I have an app that starts with tab bar with 3 items,2 of them is just a regular view controller and one of them is navigation controller and after him is table view,when I click on a cell I want to pass 2 String to the labels and to pass to a new view controller to show the label's,my problem is that after I click on the cell its looks like its jump 2 view controller's until the view controller that I want, and in the first time I didn't see my data that I pass, only after I press to come back to the table view controller(here I need to back to him from 2 view controllers), please help me to fix my code, I want to pass the data and move to a new view controller and when I want to come back to the table view I need to click just back
//Table view controller, before of him I have a navigation controller
//The identifier of the segue is "Details"
import UIKit
class HistoryTableViewController:
UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var historyTableView: UITableView!
var historyArray = [history]()
var foods = ["Milk","Honey","Salt","Bread","Banana"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return foods.count
//historyArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = historyTableView.dequeueReusableCell(withIdentifier: "cell") as? HistoryCellViewController
else {return UITableViewCell()}
// cell.ageLabel.text = String(format:"%f", historyArray[indexPath.row].age)
// cell.genderLabel.text = historyArray[indexPath.row].gender
// cell.ageLabel.text = String(format:"%f", 23)
cell.genderLabel.text = foods[indexPath.row]
cell.ageLabel.text = foods[indexPath.row]
// cell.genderLabel.text = "Bar"
//cell.historyImage.image = nil
return cell
}
var selectedAge:String = " "
var selectedGender:String = " "
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedAge = self.foods[indexPath.row]
selectedGender = self.foods[indexPath.row]
performSegue(withIdentifier: "Details", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "Details"{
let vc = segue.destination as! HistoryDetailsViewController
vc.age = selectedAge
vc.gender = selectedGender
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
foods.remove(at: indexPath.row)
historyTableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
//view controller that I want to pass after a click on a cell
import UIKit
class HistoryDetailsViewController: UIViewController {
#IBOutlet weak var ageLabel: UILabel!
#IBOutlet weak var genderLabel: UILabel!
var age:String?
var gender:String?
override func viewDidLoad() {
super.viewDidLoad()
ageLabel.text = self.age
genderLabel.text = self.gender
// Do any additional setup after loading the view.
}
//
// #IBAction func Back(_ sender: UIBarButtonItem) {
//
// // self.tabBarController?.selectedIndex = 0
// }
}
First of all, in tableView(_:cellForRowAt:) you're typecasting the dequeued cell to HistoryCellViewController.
My question is - what is the type of HistoryCellViewController? Is it a UITableViewCell or something else? In case it is a UITableViewCell you must rename it to something more relevant like HistoryCell. It is a bit confusing.
Approach-1:
Now coming to the actual problem you're facing. Instead of using the segue, try pushing the HistoryDetailsViewController manually like so,
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let controller = self.storyboard?.instantiateViewController(withIdentifier: "HistoryDetailsViewController") as? HistoryDetailsViewController {
controller.age = self.foods[indexPath.row]
controller.gender = self.foods[indexPath.row]
self.navigationController?.pushViewController(controller, animated: true)
}
}
There is no need to extra variables - selectedAge and selectedGender.
Approach-2:
In case you want to do it with the segue itself, then don't call performSegue(withIdentifier:sender:) in tableView(_:didSelectRowAt:), i.e. remove the below line of code,
performSegue(withIdentifier: "Details", sender: self)
This is because, the "Details" segue is being executed twice - once via storyboard and another via the above line of code.

swift segue from tableView through a navigationController to a TableViewController

I cannot get this to segue to another TableViewController. I keep getting a crash... I know it is because it is going through the NavigationController and I do not know how to segue from the main controller to pass it and go to the tableView. Heres the look
the segue from the navControl to the tableView is called "ChildsInfo"
Here is what I am trying and crashing.
class PagesViewController: UIViewController, UITableViewDelegate {
#IBOutlet weak var pagesTableView: UITableView!
#IBOutlet weak var infoProgressBar: UIProgressView!
let pages = ["Page 1","Page 2","Page 3"]
var myIndex = 0
var selectedPage: String?
override func viewDidLoad() {
super.viewDidLoad()
pagesTableView.dataSource = self
pagesTableView.delegate = self
// Do any additional setup after loading the view.
}
}
extension PagesViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "pagesTableViewCell")
cell?.textLabel?.text = pages[indexPath.row]
return cell!
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pages.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 71.0
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
performSegue(withIdentifier: "ChildsInfo", sender: self)
}
}
}
Based on the images you have posted I'm assuming the crash you are getting is that the segue is not found. This is because you should be trying to perform the segue to the navigation controller itself from the table view (i.e. the link on the left in your image). The navigation controller then has a root view controller and you can push others onto the stack as required.

How to refresh a ViewTable from a separate ViewController

I'm trying to create a swift program with a main ViewController, and a secondary VC that controls a pop up that overlays the screen. In this pop up, you can enter in login credentials, which will display in a tableView in the main ViewController.
So far I'm able to save the entered values in the secondary VC to core data, but I'm not able to reloadData() for the tableView in the first VC, because it just cant see the reloadData() function (must not be a public function? Not really sure, as I'm new to swift).
Could someone help me figure out the best way to go about doing this?
Main ViewController code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var account = [Account]()
#IBAction func onAddAccount(_ sender: Any) {
self.tableView.reloadData()
print("RELOADED")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func onBlank() {
self.tableView.reloadData()
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return account.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
cell.textLabel?.text = account[indexPath.row].email
cell.detailTextLabel?.text = account[indexPath.row].password
return cell
}
}
I am relatively new to swift myself. But I think what you are looking for is a Delegate will tell the main controller that the data has been updated and what it's been updated too. It also seems you might need a datasource? So that you can implement model, view, controller architecture.

swift - embedded SWRevealViewController to you application

I intergrade SWRevealViewController to my project
my project flow is
viewcontroller ---> SWRevealViewController -->menu
--> nav-->front view
the segue method from my initial view controller to SWRevealViewController is model
my problem is when my I open toggle in front view for first time only
it give me empty menu(table view)
my front view code
#IBOutlet weak var open: UIBarButtonItem!
#IBOutlet weak var result: UILabel!
#IBAction func showmore(sender: AnyObject) {
performSegueWithIdentifier("resdes", sender: sender)
}
override func viewDidLoad() {
super.viewDidLoad()
var res = Uti.get_result()
result.text = res.description
open.target = self.revealViewController()
open.action = Selector("revealToggle:")
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
// Do any additional setup after loading the view.
}
my rear code
class slidemenuVC : UITableViewController{
var menuItems = [String]()
override func viewDidAppear(animated: Bool) {
menuItems = ["Result","About us","References","Rest Test"]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menuItems.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(menuItems[indexPath.row], forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = menuItems[indexPath.row]
return cell
}
}
Second problem :
when I press at first menu item , navigation disappear
it should be like this have toggle
var cell = tableView.dequeueReusableCellWithIdentifier(menuItems[indexPath.row], forIndexPath: indexPath) as UITableViewCell
is wrong. You need your identifier has to be the actual cell id in your uitableviewcell