I am trying to add a row into my tableview before the tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int method is called. I tried to do it into the viewDidLoad() method without success is it possible ? and how ?
Here is my code :
import UIKit
class CustomTestViewController : UITableViewController {
#IBOutlet var formDetailTableView: UITableView!
var data: Data?
var firstData: FirstData?
struct CurrentFormTableView {
struct CellIdentifiers {
static let MyCell = "MyCell"
static let MyFirstCell = "MyFirstCell"
}
}
override func viewDidLoad() {
super.viewDidLoad()
//HERE ADD THE FIRST ROW ?
let cell = tableView.dequeueReusableCellWithIdentifier(CurrentFormTableView.CellIdentifiers.MyFirstCell, forIndexPath: indexPath) as! MyFirstCell
cell.displayCell(firstData)
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(CurrentFormTableView.CellIdentifiers.MyCell, forIndexPath: indexPath) as! MyCell
cell.displayCell(data[indexPath.row])
return cell
}
}
If I understand your question properly this problem can be easily :)
You always wants to show a first cell in your tableView no matter whether there is a data in your data array or not :) and your problem is you cant add the first object to data array thats all right buddy :)
Here is a solution :)
Don't do anything in ViewDidLoad :) Simply save your first row data object in your local variable lets say : yourCustomObject
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count + 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : myTestCell = tableView.dequeueReusableCellWithIdentifier("testCell")! as! myTestCell
if indexPath.row == 0 {
cell.nameLabel.text = yourCustomObject.property
}
else {
cell.nameLabel.text = data[indexPath.row -1].property
}
return cell
}
Problem solved :) Happy coding :)
How It works :
Simple,
Assume your data array is empty :) then it will return count as 0 :) But you always want to show your first cell isn't it :) so add +1 to data array count :) return data.count + 1
Now handle it carefully in cellForRowAtIndexPath. You dont want to end up accessing data in data array for first object so check for indexpath 0.
And you dont want to end up accessing object out of index of data so use data[indexPath.row -1]
Hope I made my point clear :) Happy coding
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count + 1 //Add plus 1 for firstData
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(CurrentFormTableView.CellIdentifiers.MyCell, forIndexPath: indexPath) as! MyCell
if indexPath.row == 0 {//First index will be firstData
cell.displayCell(firstData)
} else { //All other cell's will be filled with data array
cell.displayCell(data[indexPath.row - 1]) //Make sure you offset indexPath.row by 1 so you start at index 0 of data array
}
return cell
}
Related
I'm new to Swift and i've been working on an app for a couple of day now. Now I'm trying to fill up my tableview, but for some reason it stays empty. I've checked if my data comes through (by doing a print of my drinks in the updateUi function), and it seems so be there but my view just doesn't get filled. Anyone has a clue what could be wrong?
Thanks a lot!
import UIKit
class SearchResultsTableViewController: UITableViewController {
let cocktailController = CocktailController()
var drinks = [Drink]()
var drink: String!
override func viewDidLoad() {
super.viewDidLoad()
title = drink.capitalized
cocktailController.fetchDrinks(forDrink: drink)
{ (drinks) in
if let drinks = drinks {
self.updateUI(with: drinks)
}
}
}
func updateUI(with drinks: [Drink]) {
DispatchQueue.main.async {
self.drinks = drinks
self.tableView.reloadData()
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return drinks.count
}
override func tableView(_ tableView: UITableView, cellForRowAt
indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:
"DrinkCellIdentifier", for: indexPath)
configure(cell, forItemAt: indexPath)
return cell
}
func configure(_ cell: UITableViewCell, forItemAt indexPath:
IndexPath) {
let drinkItem = drinks[indexPath.row]
cell.textLabel?.text = drinkItem.strDrink
}
}
Instead of number of sections, you should use number of rows in section to return the tableview row count.
func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return drinks.count
}
I have a problem with UITableView in UIViewController.My table shows some row that I don't know why. It should be show all of row.
class TableViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
let cellIdentifier = "testCell"
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! TableViewCell
cell.lableName.text = "Hello man"
return cell
}
}
if you want hello man in 20 row.(All row)in cell for row at index path method add this line
cell.labelname.text = "Hello Man"
Please check your tableview delegate and datasource.
BTW,set right constraints.
I'm trying to present an array of names into cells of tableview controller.
Here's the code:
import UIKit
class TableViewController: UITableViewController
{
var names = ["aA", "aB", "cC"]
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return names.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)
cell.detailTextLabel!.text = names[indexPath.row]
return cell
}
}
When I simulate it, nothing has appeared into the cells!
What's wrong with my Code!
The compiler did not give me any errors.
Update number of sections. Your problem will be solved.
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
Still not solved!
I have been stuck with this problem way too long, so i hope you can help.
I Have two UITableViews side-by-side in one view in Storyboard. Each in a ContainerView to control their positions.
The idea is, if you touch a row in the first UITableView. The data from that row should be added to the second UITableView.
In TableOne i'm calling the function addDataToTableView() in didSelectRowAtIndexPath.
In Tabletwo addDataToTableView() get's the touched element and add it to the testData2 array. This works fine. The print() function spits out the right element.
But then on self.tableTwo.reloadData() the application crash with this error message:
fatal error: unexpectedly found nil while unwrapping an Optional value
I’m not entirely sure what causes the Error, but i think it’s either that i don’t get the right instance of the class, created by the storyboard or it’s something with optimals.
i tried putting in some ??? and som !!! and i have tried wrapping .reloaddata() ind another thread. but it didn’t help.
This is the entire code.
Hope you can help :)
TableOne
class TableOne: UITableViewController {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var tableTwo = TableTwo()
var testData = ["test1","test2", "test3", "test4", "test5", "test6"]
override func viewDidLoad() {
super.viewDidLoad()
tableTwo = mainStoryboard.instantiateViewControllerWithIdentifier("tableTwoId") as! TableTwo
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return testData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = testData[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableTwo.addDataToTableView(testData[indexPath.row])
}
}
TableTwo
class TableTwo: UITableViewController {
#IBOutlet var tableTwo: UITableView!
var testData2 = ["Test"]
func addDataToTableView(data: AnyObject) {
testData2.append(data as! String)
print("This works fine \(testData2[testData2.count-1] )")
self.tableTwo.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return testData2.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = testData2[indexPath.row]
return cell
}
}
If you want to send data from One TableViewController either use prepareForSegue or didSelectRowAtIndexPath.
This line let cell = UITableViewCell() you only declare an instance of a UITableViewCell by you never called the method which makes that cell reusable in the queue.
class TableOne: UITableViewController
{
var testData = [String]()
override func viewDidLoad()
{
super.viewDidLoad()
testData = ["test1","test2", "test3", "test4", "test5", "test6"]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return testData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier", forIndexPath: indexPath)
cell.textLabel?.text = testData[indexPath.row]
return cell
}
"CellIdentifier" is the name of the cell identifier from the tableView cell prototype into the storyboard
To send Data the TableView lets say we are using prepareForSegue and you must know that When the user selected one cell only that cell information will be sent to your next ViewController.
if segue.identifier == "NAME_OF_THE_SEGUE_IDENTIFIER"
{
let destination = segue.destinationViewController as("nameOftheTableView")
let indexPath = mytableview.indexPathForSelectedRow!
var dataToTransfer = testData[indexPath.row]
// let's say you have a string variable into your next ViewContrller called receiver
destination.receiver = dataToTransfer //<-- from the selectRow we assign that value into our next Controller.
}
So Build up on that to fix your code :)
Lets say that I have three arrays in my ViewController. Two of them represent section cells and one represents the sections.
How do I append a TableViewCell to a specific Section?
ViewController.swift:
// represents my 2 sections
var sectionNames = ["Switches","Settings"]
// data for each section
var switchData = ["switch1","switch2", "switch3"]
var settingData = ["setting1", "setting2"]
A better approach would be to use a dictionary instead of separate arrays:
let data: Dictionary<String,[String]> = [
"Switches": ["switch1","switch2","switch3"],
"Settings": ["setting1","setting2"]
]
Here the dictionary keys are the sections and the values arrays are the data for each section.
So, a tableViewController might look like this:
class MyTableViewController: UITableViewController {
let data: Dictionary<String,[String]> = [
"switches": ["switch1","switch2","switch3"],
"settings": ["setting1","setting2"]
]
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return data.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
let sectionString = Array(data.keys)[section]
return data[sectionString]!.count
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let sectionString = Array(data.keys)[section]
return sectionString
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
let sectionString = Array(data.keys)[indexPath.section]
cell.textLabel?.text = data[sectionString]![indexPath.row]
return cell
}
}
Result: