hidesBarsOnSwipe will show toolbar unexpectedly - ios

I set hidesBarsOnSwipe=true in two view controllers, the Foo view controller which does not have a toolbar pushes Bar view controller which does have a toolbar. When Bar pop back to Foo, the toolbar will show when I scroll the Foo view controller. If I don't set self.navigationController?.toolbarHidden = false in Bar view controller, the toolbar will not show in neither Bar nor Foo view controller. I work with iOS8 SDK + Xcode 7.1.1 + Swift 2.1.
class FooTableViewController : UITableViewController
{
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.hidesBarsOnSwipe = false
self.navigationController?.toolbarHidden = true
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.toolbarHidden = true
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "12345678"
return cell
} }
class BarTableViewController : UITableViewController
{
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.hidesBarsOnSwipe = true
self.navigationController?.toolbarHidden = false
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.hidesBottomBarWhenPushed = false
self.navigationController?.toolbarHidden = true
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "12345678"
return cell
}}

You are up against 2 problems:
You cannot add anything to a UITableViewController
All the programmatic toolbarHidden and hidesBarsOnSwipe is only confusing the OS,and you will end up with toolbars on the wrong layer, scrolling along with the table view, and similar oddities with the navigation bar.
What you want is for the second table view to be handled by a UIViewController, not a UITableViewController. There is little programmatic change, you only need your UIViewController to adopt the data source and table delegate protocols.
No need to tinker with showing/hiding the toolbar. The code is much simpler, you can define everything not listed below in the Storyboard.
Foo (no toolbar):
class FooTableViewController: UITableViewController {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Foo \(indexPath.row)"
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("Bar", sender: self)
}
}
Bar (with toolbar):
class BarTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Bar \(indexPath.row)"
return cell
}
}
Final Product:
► Find this solution on GitHub and additional details on Swift Recipes.

Related

How to show and hide the header in section of tableView by navigation bar button tapped?

Developing an iOS application with Xcode ver 9.3, Swift.
Could you tell me how to show and hide(switch) the header in section of tableView by navigation bar button tapped?
Search bar is put in header in section to make it always visible while scrolling tableview
I would like to hide the search bar in the initial display
and, show and hide the search bar by tapping navigation bar button
The code and the screenshot are as follows.
Code
import UIKit
class TableViewController: UITableViewController, UISearchBarDelegate {
let array = ["apple", "orange", "melon", "banana", "peach"]
let searchBar = UISearchBar()
override func viewDidLoad() {
super.viewDidLoad()
let searchButton = UIBarButtonItem(title: "Search", style: UIBarButtonItemStyle.plain, target: self, action: #selector(searchTapped))
self.navigationItem.leftBarButtonItem = searchButton
}
#objc func searchTapped() {
// If searchBar is hidden, then show a searchBar.
// If searchBar is shown, then hide a searchBar.
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
searchBar.delegate = self
searchBar.placeholder = "Search..."
searchBar.showsCancelButton = true
return searchBar
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
searchBar.sizeToFit()
return searchBar.frame.height
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = array[indexPath.row]
return cell
}
}
Screenshot
var hideSearchBar = false // Class global var
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return hideSearchBar ? 0.1 : searchBarHeight
}
#IBAction func search(sender: UIBarButtonItem) {
hideSearchBar = !hideSearchBar
tableView.reloadData()
}
Remember to keep height of section header as 0.1 if you want to hide searchBar. Keeping height 0 won't work.
You could use tableView:heightForHeaderInSection: Appledoc from UITableViewDelegate method. As follows
override viewDidLoad() {
super.viewDidLoad()
yourBarButtonTapped = false
//rest of your code
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return yourBarButtonTapped ? 0.1 : current_height
}
#IBAction func barButtonTapped() {
yourBarButtonTapped = true
yourTableView.reloadData()
}
You can do this:
#objc func searchTapped() {
// If searchBar is hidden, then show a searchBar.
tableView.tableHeaderView = self.searchBar;
// If searchBar is shown, then hide a searchBar.
tableView.tableHeaderView = nil;
tableView.reloadData();
}
Or you could define:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// if you don't need header then return nil or return uiview for header...
}

UITableView Reordering Of Cells-Reorder/Edit Mode Not Displaying (Swift)

I have a UITableView inside a UIViewController. I am trying to make it so when the user click the BarButtonItem in the NavigationBar, that the tableview goes into editing mode, and thus the user can drag and reorder the cells.
However, what happens is that I simply press the editing button, and nothing happens.
This is what I have tried:
For the array declaration:
var tester = ["1", "2", "3"]
For the button declaration:
#IBAction func editButtonPressed(sender: AnyObject) {
self.editing = !self.editing
}
For the various tableview functions:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return tester.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("editCell", forIndexPath: indexPath) as! EditTableViewCell
cell.nameHolder?.text = tester[indexPath.row]
// Configure the cell...
return cell
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
var itemToMove = tester[fromIndexPath.row]
tester.removeAtIndex(fromIndexPath.row)
tester.insert(itemToMove, atIndex: toIndexPath.row)
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
What could be causing this bug?
Swift 4.1
In → func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
Add this line to configure the cell:
cell.isEditing = self.tableView(tableView, canMoveRowAt: indexPath)
Ran Hassid has the most correct answer to this in his comment.
This will solve the problem:
#IBOutlet weak var tableView: UITableView!
#IBAction func editButtonPressed(sender: AnyObject) {
tableView.setEditing(!tableView.isEditing, animated: true)
}

Make each item in the tabel view clickable to perform action - Swift

i am pretty new to ios development. I have a table view with 2 Sections
TableView:
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate{
var people = ["ABC","PQR","LMN"]
var languages = ["Android","Java","C++",".Net"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section==0
{return people.count}
else
{return languages.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
if indexPath.section==0{
cell.textLabel?.text = people[indexPath.row]
}
else{
cell.textLabel?.text = languages[indexPath.row]
}
return cell
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section==0{
title="Names"
}
else{
title="Languages"
}
return title
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
I want make each item in the table view clickable. That is when an item from the table view is clicked a new corresponding table view opens. Can someone help me with it ?
All you need if a if/switch statement in your didSelectRowAtIndexPath section. For example :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if (indexPath.row == 0) {
//do something
}
else if (indexPath.row == 0) {
//do something else
}
}
According the fact you want a new table view after click, I think you should perform a segue to present a new view controller. See here : How to segue programmatically using swift
You can achieve navigation on other controller like this,
First you need to embed Navigation controller with your view so you can navigate easily.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if (indexPath.row == 0)
{
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("AddVC") as! addRecordViewController
self.navigationController?.pushViewController(vc, animated: true)
}
else
{
// Navigate on other view
}
}
Hope this will help.

swift table view controller is not scrollable

this is my code:
class PlayersNamesTableViewController: UITableViewController {
var players = [Player]()
let numberOfPlayers = 30
override func viewDidLoad() {
super.viewDidLoad()
loadPlayers()
}
func loadPlayers(){
for index in 0..<numberOfPlayers{
let player = Player(name: "Player \(index)")
players += [player]
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return players.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("playerCellIdentifier", forIndexPath: indexPath) as UITableViewCell
let player = players[indexPath.row]
cell.textLabel?.text = "\(player.name)"
return cell
}
}
in my storyboard, i select Basic for the style of the cell.
My problem is that the table view is not scrollable, i just can see the first 14 players, like this:
Update 1
I put print("\(indexPath.row)") on the override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { method and I can see that there are just 15 values being printed, where are the other 30?
Update2
Scroll is enabled on the table view
Update3
User Interaction is enabled, as u see here
Here is your answer. Check your mouse. In simulator you should click to screen and scroll.

Complete In-Depth switch statement malfunction

I have asked this question once before however I feel like i haven't been as thorough as can be. I am attempting to complete a very standard drill down table view hierarchy programmatically rather than using the IB to avoid unnecessary scramble due to the fact i have well over 40 different views i want to implement. I have decided to use the following switch-statement:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var VC: UITableViewController
switch indexPath.row {
case 0: VC = SecondTableViewController()
default: ()
}
navigationController?.pushViewController(VC, animated: true)
}
as you can see it gives me the non-initialized error, so i then proceed to make my variable an optional to fix this issue & it compiles and runs:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var VC: UITableViewController?
switch indexPath.row {
case 0: VC = SecondTableViewController()
default: ()
}
navigationController?.pushViewController(VC!, animated: true)
}
however when i select the designated row (which is correct at the value of 0 after running under the debugger) it crashes with this error:
what seems to be the issue? is it the default statement within my switch? or is it the variable within my "pushViewController" method? Might i add, when i change the parameter within this method from "VC/VC!" to "UITableViewController()" like such:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var VC: UITableViewController?
switch indexPath.row {
case 0: VC = SecondTableViewController()
default: ()
}
navigationController?.pushViewController(UITableViewController, animated: true)
}
it runs & functions accordingly, but when the view is pushed, it is not to the TableViewController i designated in my switch statement, rather then just a blank table view. what am i missing?
HERE IS THE CODE FOR MY SecondTableViewController :
import UIKit
class SecondTableViewController: UITableViewController {
var myVariable = ["LIST OF STRINGS IN AN ARRAY"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myVariable.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as! UITableViewCell
var superVariable = myVariable [indexPath.row]
cell.textLabel!.text = superVariable
return cell
}
}
The problem lies in SecondTableViewController where you didn't define an identifier for your cell. You should do something like this,
class SecondTableViewController: UITableViewController {
let theData = ["one", "two", "three", "four"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = theData[indexPath.row]
return cell
}
}

Resources