Swift - Detail View Controller depending on Table View Cell - xcode

i have a basic table view controller with dynamic prototypes,
there can appear 4 cells, but there also can appear 6 cells.
What i want is:
Depending on which cell is clicked to switch to another "detail"-ViewController.
my first thought is like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if cell1clicked {
// go to viewcontrollerA
} elseif cell2clicked {
// go to viewcontrollerB
} elseif cell3clicked {
// go to viewcontrollerC
} else {
// go to viewcontrollerD
}
}
is this even possible with tableviewcontrollers?
Greetings and thanks!

Its possible to do it by using TableViewController in storyboard and use static cells instead of dynamic.
Here is the way:
1- Define 4 cells in your static tableView.
2- Drag 4 View Controller in storyboard.
3- Connect First Cell with viewcontrollerA and so on in Storyboard.
4- Be sure that you subclass your class UITableViewController and remove tableview methods.
Update :
If you want to use dynamic cells its possible to push the ViewController programmatically :
1- Drag 4 ViewControllers and go to identity inspector and give each
one a Storyboard ID.
2- Create 4 classes for your ViewControllers and connect each
storyboard with its class.
2- Add Navigation Controller to your initial ViewController in
storyboard.
Ive made you a sample class here :
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource{
var array = ["First","Second","Third","Fourth"]
#IBOutlet weak var tableviewmy: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = array[indexPath.row]
return cell;
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
var controller1 : FirstViewController = storyboard?.instantiateViewControllerWithIdentifier("ViewControllerA") as! FirstViewController
self.navigationController?.pushViewController(controller1, animated: true)
}else if indexPath.row == 1{
var controller2 : SecondViewController = storyboard?.instantiateViewControllerWithIdentifier("ViewControllerB") as! SecondViewController
self.navigationController?.pushViewController(controller2, animated: true)
}else if indexPath.row == 2 {
// controller 3
}else {
// controller 4
}
}
}
You may download a sample project :
https://yadi.sk/d/F5Qb85MLiMPqk

Related

Why the cell height is not changing on tapping the button once. It is working only when I tap the button twice

Click Here To see the UI of my app
Here In the image you can see the ui.
--> There is a tableView & a button on the main view.
--> I have taken a custom tableViewCell class
In the cell I have taken a UIView
Constraints Added To That View are:
centre horizontally, height, width, top & bottom constraint
I have added a outlet of the height constraint to the TVCell class
--> I have taken a button and added a event handler to it
--> Button Event handler:
In button event handler I am just changing the height of the view in the first cell and reloading the cell.
Now the problem is that height of the cell is changing when I tap on the button. But its happening only when I tap one the button twice. So I want to know why is it happening. Here I am adding my code below.
I have one solution for this problem which you can see after you see after the code of the ViewController & TableViewCell Class
VIEW CONTROLLER CLASS
import UIKit
class ViewController: UIViewController,UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.separatorColor = UIColor.black
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
return cell
}
#IBAction func buttonAction(_ sender: Any) {
let indexPath = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
if cell.viewHeightConstraint.constant == 75 {
cell.viewHeightConstraint.constant = 10
}
else{
cell.viewHeightConstraint.constant = 75
}
tableView.reloadRows(at: [indexPath] , with: UITableView.RowAnimation.automatic)
}
}
TABLEVIEWCELL CLASS
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var viewHeightConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
//Setting View Height To 75
viewHeightConstraint.constant = 75
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
You can get this source code from this link below
https://github.com/himansudev/tableViewIssue_15_4_20_1.git
Now I have a solution for this problem but I believe its not a proper solution. So what I have done is as shown below
1) I have modified the button event handler, see below is the modified code. Please refer to the above code to identify the changes that I have made to this event handler
#IBAction func buttonAction(_ sender: Any) {
let indexPath = IndexPath(row: 0, section: 0)
tableView.reloadRows(at: [indexPath] , with: UITableView.RowAnimation.automatic)
}
2) Secondly I have added this extra piece of code , see below
override func viewDidLayoutSubviews() {
print("viewDidLayoutSubviews")
let indexPath = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
if cell.viewHeightConstraint.constant == 75 {
cell.viewHeightConstraint.constant = 10
}
else{
cell.viewHeightConstraint.constant = 75
}
}
Find the source code after changes below
https://github.com/himansudev/tableViewSolution_15_4_20_1.git
Now after doing these two changes it is working (but sometimes it doesn't work when I tap on the button rapidly many times) but the problem is the viewDidLayoutSubviews() is not getting called but when I comment it than the cell is not working as expected .
SO I want to know why is it behaving that way???
First of all you need to add also the UITableViewDelegate to your ViewController and a var like this:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var cellHeight: CGFloat = 75
and the heightForRow function which will return the right Height:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeight
}
Then on your button action:
#IBAction func buttonAction(_ sender: Any) {
if cellHeight == 75 {
cellHeight = 10
}
else{
cellHeight = 75
}
tableView.reloadData()
}
Also remove the constraint viewHeightConstraint because you do not need it.

Xcode 7 - Cell content not displayed into an empty label

I'm trying to display a cell content into an empty UILabel, but after I upgraded to Xcode 7, the content didn't show up. I was following the same mechanism and it worked on Xcode 6, but since I'm new to Swift I may have something wrong in the code.
TableViewController:
import UIKit
class TableViewController: UITableViewController {
struct dataModel {
var name:String
var val:Double
}
let foods = [dataModel(name: "name1", val: 3.3),
dataModel(name: "name2", val: 5.5)]
#IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return foods.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
// Configure the cell...
let foodCell = foods[indexPath.row]
cell.textLabel?.text = foodCell.name
return cell
}
var valueToPass:String!
var valueInt:Int!
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
valueToPass = currentCell.textLabel!.text
performSegueWithIdentifier("showCalc", sender: self)
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showCalc") {
let viewController = segue.destinationViewController as! calcViewController
viewController.passedValue = valueToPass
}
}
}
ViewController where I want to display the tapped cell into an empty label:
import UIKit
class calcViewController: UIViewController {
#IBOutlet var text: UILabel!
#IBOutlet var empty1: UILabel!
var passedValue:String!
override func viewWillAppear(animated: Bool) {
empty1.text = passedValue
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
As a result, there is no error, but there is nothing displayed inside the empty label.
The other thing I want to achieve is to display the Int value into another label and then do some calculations, but this would be another question. Thanks in advance!
There are several issues in this code. First you are obviously missing some closing braces. But I assume this is a copy-paste error.
Why do you use didDeselectRowAtIndexPath? Don't you have a segue from the table view cell to the next controller? Then you should get the text label in prepareForSegue by using tableView.indexPathForSelectedRow.
If you like to keep it this way you should use didSelect... in stead of didDeselect....
You should take the value you want to pass to the next view controller direct from the data and not from the cell. You have the data you present in the table in the foods array.
Class names should always start with a capital letter. ALWAYS!
Having the data model within the controller is poor design. You should have the struct separated in its own file. In this case you could even hand the complete data object to the next view controller.

Why this UITableViewController doesn't show anything?

I'm using the latest beta of Xcode 7. I'm programming a simple UITableView, but this doesn't work well, the inspector error doesn't show anithing but when I start the simulator, the App crash. Can someone help me?
// RestaurantTableViewController.swift
import UIKit
class RestaurantTableViewController: UITableViewController {
var restaurantNames = ["Cafe Deadend", "Homei", "Teakha", "Cafe Loisl", "Petite Oyster", "For Kee Restaurant", "Po's Atelier", "Bourke Street Bakery", "Haigh's Chocolate", "Palomino Espresso","Upstate","Traif","Graham Avenue Meats","Waffle & Wolf", "Five Leaves", "Cafe Lore", "Confessional", "Barrafina", "Donostia", "Rpyal Oak", "Thai Cafe"]
var restaurantImages = ["cafedeadend.jpg", "homei.jpg", "teakha.jpg", "cafeloisl.jpg",
"petiteoyster.jpg", "forkeerestaurant.jpg", "posatelier.jpg", "bourkestreetbakery.jpg",
"haighschocolate.jpg", "palominoespresso.jpg", "upstate.jpg", "traif.jpg",
"grahamavenuemeats.jpg", "wafflewolf.jpg", "fiveleaves.jpg", "cafelore.jpg",
"confessional.jpg", "barrafina.jpg", "donostia.jpg", "royaloak.jpg", "thaicafe.jpg"]
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.restaurantNames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
// Configure the cell...
cell.textLabel!.text = restaurantNames[indexPath.row]
cell.imageView?.image = UIImage(named: restaurantImages[indexPath.row])
return cell
}
}

Repeating values in Stepper inside TableViewCell when scrolling

Stepper problem when cells need scroll.
My_TableViewCell.swift
import UIKit
class My_TableViewCell: UITableViewCell {
#IBOutlet weak var My_Label1: UILabel!
#IBOutlet weak var My_Label2: UILabel!
#IBOutlet weak var My_Stepper: UIStepper!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
...
My_TableViewController.swift
import UIKit
var My_Ids = ["C01","C02","C03","C04","C05","C06","C07","C08","C09","C10"]
var My_Values = ["0","0","0","0","0","0","0","0","0","0"]
class My_TableViewController: UITableViewController {
#IBAction func My_Stepper(sender: AnyObject) {
let point = sender.convertPoint(CGPointZero, toView: tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(point)!
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! My_TableViewCell
cell.My_Label2.text = "\(Int(cell.My_Stepper.value))"
}
...
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return My_Ids.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell =
self.tableView.dequeueReusableCellWithIdentifier(
"My_TableCell", forIndexPath: indexPath)
as! My_TableViewCell
let row = indexPath.row
cell.My_Label1.text = My_Ids[row]
cell.My_Label2.text = "\(Int(cell.My_Stepper.value))"
return cell
}
...
When all cells fit in a "page" the Stepper works well but if the cells are resized and you need scroll the tableview the values are repeated in other cells.
If you alter the value on the cells C06 and C07 this will to reflect C01 and C02 cells and vice-versa.
Please view this image showing the snapshots with the errors
UITableViewController intentionally reuses cells as an optimization. You need to clear the old cell settings as part of your solution. Add a prepareForReuse method to your My_TableViewCell class.
You do this:
- (void) prepareForReuse
{
[super prepareForReuse];
// clear previous cell settings
}
Additional Notes:
recommend against calling cellForRowAtIndexPath directly. See this thread.
recommend you use Pascal casing for class names: Use MyTableViewCell instead of My_TableViewCell.

Table View displays blank screen

I am having issues with with a TableViewController displaying a blank screen. I have just changed my 'Personalisation' screen from a ViewController to a TableViewController however when the personalisation cell is tapped and the app segues to the personalisation screen, all that is displayed is a blank screen.
Here is an image of how it should look as well as how it used to look on the right:
This is how it looks when run:
The content is set to Static and style set to Grouped.
This is the only code I have at the moment as I haven't finished transitioning the code from the old version to the new version since I just ran into this issue...
import UIKit
class PersonalisationTableViewController: UITableViewController, UIPickerViewDelegate {
#IBOutlet weak var changeButton: UIButton!
#IBOutlet weak var userNameTextField: UITextField!
let coloursArray = ["Default (Blue)", "Green", "Orange", "Purple", "Red", "Turquoise"]
#IBAction func userNameChange(sender : AnyObject) {
//Closes keyboard when user touches enter button
userNameTextField.resignFirstResponder()
globalUserName = userNameTextField.text
globalUserName = globalUserName.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
userNameTextField.placeholder = globalUserName
userNameTextField.text = ""
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 0
}
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return 0
}
/*
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell
// Configure the cell...
return cell
}
*/
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView!, moveRowAtIndexPath fromIndexPath: NSIndexPath!, toIndexPath: NSIndexPath!) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView!, canMoveRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
/*
// 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!) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
}
I've not worked with table views much so I'm sure the issue is obvious, but I can't figure it out.
It is most likely because your numberOfSectionsInTableView and numberOfRowsInSection methods are returning 0. You have your UITableView set up in your storyboard but the two methods override that. When you have static cells in your UITableView, you should not override these two methods. They were probably left over from when you created the class as a subclass of UITableViewController.
Here is what is basically happening: Your UITableViewController hooked up to your PersonalisationTableViewController file. When your PersonalisationTableViewController sets up the sections and rows for your tableView, it is setting the sections to 0 and the rows for each section to 0.
I just tried putting the two methods into one of my apps that has static cells and I can confirm that it appears blank.
If you were programmatically creating your views, you could have done the following:
override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
// Return the number of sections.
return 2
}
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return 1
// Or this if you had a different number rows for each section:
if section == 0 {
return //someInt
} else if section == 1 {
return //someOtherInt
} else {
//......
}
}
EDIT: Also, I believe this is a bug with Xcode but you must override:
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
if indexPath.section == 0 {
return someHeight
} else if indexPath.section == 1 {
return someOtherHeight
} else {
// ....
}
}
This error has a very simple fix:
Select the ViewController Scene. Now, select the inspector panel from the sidebar options. Check the “Is Initial View Controller” attribute option, save the project and build the project again.

Resources