iOS - UITableView add single static cell to dynamic table - ios

I Have a UITableView which is controlled by NSFetchedResultsController. I want to add single cell to the first row and make this cell static. In other words, there will be a button which will open another View Controller.
Until now, I was ok with fetched results controller and table. Now I'm a bit confused. How should I do this?
Instead using a header might be ok too, but I don't want this header to be on top all the time. I want this cell to be just like WhatsApp iOS "Create new group" cell on chats panel.
Thank you!

var dataArray = ["A","B","C"]
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataArray.count+1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if indexPath.row == 0
{
let cell = tableView.dequeueReusableCell(withIdentifier: "CreateNewGroupCell") as! CreateNewGroupCell
return cell
}
else
{
// Get the data from Array
let data = self.dataArray[indexPath.row-1]
// Logic to show other cells
let cell = tableView.dequeueReusableCell(withIdentifier: "OtherCell") as! OtherCell
return cell
// ....
}
}

You will need to create tableview with number of rows fetched from NSFetchedResultsController +1. Also in cellForRowIndex method you will need to add a check like indexPath.row == 0 and in there you will make the changes.
Also you will have to add action for that button within that section. You can also set different custom tableview for first row.
It can be similar to following:
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell {
if(indexPath.row==0){
let cell = tableView.dequeueReusableCell(withIdentifier: "CellWithButton", for: indexPath) as! CellWithButton
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: "OtherCells", for: indexPath) as! OtherCells
//here add data for cells from your array
}
return cell
}

Related

How to implement two xib cells and single . Array count is nil show empty one otherwise show with data cell

How to implement two xib cells and only one array, if array count is nil show empty xib cell and if array count is not nil show xib cell with data swift. Please solve the problem i have searched lot of no answer is related to me.
This example assumes your data array is named myData:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return either 1, or the count of your data, whichever is greater
return max(1, myData.count)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// if it's the first row, and your data is empty
if indexPath.row == 0 && myData.count == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "emptyCell", for: indexPath) as! EmptyCell
return cell;
}
let cell = tableView.dequeueReusableCell(withIdentifier: "dataCell", for: indexPath) as! DataCell
// populate the cell
return cell
}

How to access specific row by index

I've a table view controller in which I want to dynamically create a row (cell). How can I access row by index number in Swift? The following is what I did and now I'm stuck here.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "teamStats", for: indexPath) as! TeamStatsTableViewCell
return cell
}
This is my TableViewController code in which I want to check if the row is at a specific index number.
This method is a delegate method which will be called every time a cell is displayed on your UITableView. So if you want to do something with a cell in a particular index, you do the following. Please go through Apple docs and get a better understanding of what delegate methods are.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "teamStats", for: indexPath) as! TeamStatsTableViewCell
if indexPath.row == requiredIndex {
//Do something.
}
if indexPath.row == lastIndex { // you have the last index with you. replace this variable with that.
cell.firstlabel.text = ""
}
return cell
}
Please try this code:
if indexPath.row == 1{
//Your code
}
You can check the section :
if indexPath.section == 1{
}
It may helps to you.Thank you

Table view did select method to handle check box image

I have an table view with three cell which contains the label and one image (check box).Now when ever i select any cell.That particular cell image (check box) alone needs to get tick.png. And remaining two cell image should be untick.png.
But now if i select first cell then the first cel image get as tick.png.Then if i select second and third cell.That cell image also getting tick.png
But i need only one image alone needs to tick.png.Which ever table view cell i am selecting that particular cell image alone needs to be tick.png.And remaining two cell image should be untick.png.
My code :
var Data: [String] = ["First","Second","Third"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.Data.count > 0{
return self.Data.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ViewCell
cell.Lbl.text = self.aData[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! suggestionCell
cell.suggestionImg.image = UIImage(named: "tick")
}
If I understand you correctly you only want a single check mark at any given time. If this is true then you would simply setup a property in your view controller like this:
var checkedRow: Int
and set the row index in tableView(_:didSelectRowAt:). By setting it to -1 you would disable all check marks. Then in tableView(_:, cellForRowAt:) you would conditionally enable the check mark for the cell if indexPath.row is equal to checkedRow:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
checkedRow = indexPath.row
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ViewCell
if indexPath.row == checkedRow {
cell.suggestionImg.image = UIImage(named: "tick.png")
cell. suggestionLbl.text = "<ticked text>"
} else {
cell.suggestionImg.image = UIImage(named "untick.png")
cell. suggestionLbl.text = "<unticked text>"
}
return cell
}
As an add-on to Tom's answer, I suggest storing IndexPath instead of Int adding also a
var lastCheckedRow:IndexPath = IndexPath(row: 0, section: 0)
This allows you to only reload the newly checked row and the previously checked row instead of the whole table view plus it will support multiple sections too. It does not matter much at your current stage where there is only 3 rows but for larger table views this will be more efficient. Also it removes the blinking effect of UITableView.reloadData().
The code is something like:
//0 based on assumption that first cell is checked by default
var checkedRow:IndexPath = IndexPath(row: 0, section: 0)
var lastCheckedRow:IndexPath = IndexPath(row: 0, section: 0)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Update checkedRow for reload but keep track of current tick
lastCheckedRow = checkedRow
checkedRow = indexPath
//Remove previous tick
tableView.reloadRows(at: [lastCheckedRow], with: .automatic)
//Update new tick
tableView.reloadRows(at: [checkedRow], with: .automatic)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ViewCell
if indexPath.row == checkedRow {
cell.suggestionImg.image = UIImage(named: "tick.png")
} else {
cell.suggestionImg.image = UIImage(named "untick.png")
}
return cell
}
You can also play around to create an ideal visual effect when ticking different cell by changing the with:UITableViewRowAnimation parameter which I use .automatic for the example.
allowsMultipleSelection: Is only easiest thing that will help you.
Add following line in your viewDidLoad after setting up the tableView
override func viewDidLoad() {
// ... setup you need
tableView.allowsMultipleSelection = false
}
Hope this helps!

Programmatically Create Static TableView / Cells

I have a UITableView, which as an example contains dynamic cells I create based on the content of an array.
I can populate these using the count of the array and indexPath to render a cell per item. I am happy with this and it works well.
I would like to try now and create static cells programmatically.
Immediately however I am stumped, how do I create this? I'm currently overriding numberOfRowsInSection and cellForRowAt indexPath as follows:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! ProfileCell
cell.rowContent.text = items[indexPath.row]
return cell
}
I suspect my first mistake is dequeueReusableCell and would really appreciate any help.
If I understood your question, you want to add a static cell in a tableView that contains dynamic cells.
If that is the case, you could hardcode this, increasing the return value here:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count+1
}
In this case, you want to add just one static cell.
In cellForRowAtIndexPath, you should define where you want to add this static cell. In the example below, it would be the first cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
//should change StaticCell to the static cell class you want to use.
let cell = tableView.dequeueReusableCell(withIdentifier: "staticCell", for: indexPath) as! StaticCell
//hardcore attributes here, like cell.rowContent.text = "A text"
return cell
}
let row = indexPath.row-1
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! ProfileCell
cell.rowContent.text = items[row]
return cell
}
It's basically about shifting the items[row] according to the number of static cells you want to use.
I'm not sure if that will work, but would be my first guess (according to my experience about that). Try this and tell me if it worked :)

for loop only shows first item in array when trying to display in tableView

I'm trying to display tableview cells based on items in an array but for some strange reason it will only display the first item in the array. When I use a print statement it shows the array it being iterated through correctly.
Here is the array:
var restaurants = ["Truckyard", "EasySlider", "Revolver", "Armoury"]
Here is the cellForRowAtIndexPath:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = restaurantTableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! restaurantCell
for rest in restaurants {
cell.restaurantImageView.image = UIImage(named: rest)
cell.restaurantNameLabel.text = rest
}
return cell
}
cellForIndexPath is called once for each row. Try this instead:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = restaurantTableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! restaurantCell
cell.restaurantImageView.image = UIImage(named: restaurants[indexPath.row])
cell.restaurantNameLabel.text = restaurants[indexPath.row]
return cell
}
No need for a loop. cellForRowAt is providing you with an indexPath. Check the indexPath.row property. If you only have one section, the row is the index of the item in your array you want to access. You are basically iterating over your array for each row and this will inevitably set your last item as the title/image

Resources