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.
Related
I'm a high school student working on an app in Xcode 8 using Swift 3. I am trying to create a way to create a table view with collapsible sections. I am trying to create a way to have my code create a view that pushes all of the data into organized sections. Im trying to have my data displayed through using an extension. Even when I have a breakpoint after the extension it never reaches that point.
Edit: The rest of the app is built within the Main.storyboard, however (as you can see), this tableViewController is built entirely within code.
I can create a segue to the WeaponSelectVC however, none of the information and sections are displayed. Breakpoints inside the datasource/delegate methods do not 'break' the program and no information is displayed.
Edit #2: From the storyboard, I segue to this TableViewController (WeaponSelectVC) using the following code after a button is pressed:
let window = UIWindow(frame:UIScreen.main.bounds)
window.makeKeyAndVisible()
window.rootViewController = UINavigationController(rootViewController: WeaponSelectVC())
I can see the table loaded for an instant before the Main.Storyboard ViewController (with the button) gets loaded on top of this.
The Table does not contain any of the information or sections when we see it for an instant (it also isn't loaded when I open this separately).
Below is the code from the WeaponSelect class:
struct section {
var name: String!
var items: [String]!
var collapsed: Bool
init(name: String, items: [String], collapsed: Bool = false) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
class WeaponSelectVC: UITableViewController {
var sections = [section]()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Weapons"
// Initialize the sections array
// Here we have three sections: Mac, iPad, iPhone
sections = [
section(name: "Canadian Weapons", items: ["Colt-browning machine gun M1895/14 (Canadian)","Lee Enfield (Canadian)", "Ross Rifle MK III(Canada)", "Webley revolver (Canadian)", "Lewis (Canadian)", "Mills bomb (Canadian)"]),
section(name: "German Weapons", items: ["KAR-98K (German)", "Mauser Gewehr 98 (German)", "Luger (German), Stick grenade (German)"]), ]
// self.tableView.reloadData()
self.tableView.dataSource = self
// self.tableView.delegate = self
// self.tableView.reloadData()
}
}
extension WeaponSelectVC {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return sections.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].items.count
}
// Cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as UITableViewCell? ?? UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return sections[indexPath.section].collapsed ? 0 : 44.0
}
// Header
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") as? CollapsibleTableViewHeader ?? CollapsibleTableViewHeader(reuseIdentifier: "header")
header.titleLabel.text = sections[section].name
header.arrowLabel.text = ">"
header.setCollapsed(sections[section].collapsed)
header.section = section
header.delegate = self
return header
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44.0
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 1.0
}
}
//
// MARK: - Section Header Delegate
//
extension WeaponSelectVC: CollapsibleTableViewHeaderDelegate {
func toggleSection(_ header: CollapsibleTableViewHeader, section: Int) {
let collapsed = !sections[section].collapsed
// Toggle collapse
sections[section].collapsed = collapsed
header.setCollapsed(collapsed)
// Adjust the height of the rows inside the section
tableView.beginUpdates()
for i in 0 ..< sections[section].items.count {
tableView.reloadRows(at: [IndexPath(row: i, section: section)], with: .automatic)
}
tableView.endUpdates()
}
}
From which class is the WeaponSelectVC inherited? Your extension should be inheriting from UITableView .
Your extension class should look like
extension UITableView {
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.
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
}
}
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
In swift, if I create a new cocoa touch class of type UITableViewController, I am given this file called TableViewController.swift:
import UIKit
class TableViewController: UITableViewController {
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.
}
*/
}
When I uncomment this provided method:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell
// Configure the cell...
return cell
}
I am greeted with this compiler error: "Overriding method with selector 'tableView: cellForRowAtIndex path has incomplete type..."
Is there something I can do to fix this or is this just a beta issue?
The tableView:didSelectRowAtIndexPath: method's declaration has changed between Xcode 6 beta 6 and Xcode 6 beta 7. This method now requires non-optional parameters and returns a non-optional UITableViewCell.
So, with Xcode 6 beta 7, you have to set the following lines in your UITableViewController subclasses in order to avoid error messages:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
...
}
instead of:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
...
}
See Apple Developper Library for more details.