I am working on a UITableView with a custom row (single row), that I load from a separate xib file. UITableView also has a sticky footer view.
Everything is working fine except that when I tap on the footer view, the UITableView's delegate method tableView(_:didSelectRowAt:) is being called, and that's weird.
The IndexPath that I received inside that method is [0,0]. Now how that is problematic for me? Well I am doing a certain thing when the cell of that tableview is pressed. But under the current scenario, that certain thing is also being done when I press footer view instead of the cell.
The code for UITableView is:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(
withIdentifier: CellIdentifiers.INVITE_CELL_ID,
for: indexPath) as? InviteCell else {
return UITableViewCell()
}
// cell configuration
return cell
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
if (contacts.count > 0) {
guard let footer = tableView.dequeueReusableCell(
withIdentifier: CellIdentifiers.INVITE_FOOTER_CELL_ID)
as? InviteFooter else {
return nil
}
footer.delegate = self
return footer
}
return nil
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if (contacts.count > 0) {
return 90
}
return 0
}
Related
I've currently multiple items in tableView cell .I want to increase the height of cell when text condition is matched like if name = "john" then increase the height of cell without disturbing another cell. I want to achieve this screenshot result
My current code is
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == tableOrder {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.tableOrderHeight.constant = self.tableOrder.contentSize.height
//self.tableOrderHeight.constant = (6 * 80)
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath ) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PriceTVCell.self)) as? PriceTVCell else {return UITableViewCell()}
return cell
}
first get the index of the row you want to increase the height and use the delegate function heightForRowAt.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == customRow {
return 100.0;//Choose your custom row height
}
}
I'm trying to add a button at the bottom of a table view to handle a loadMore() function.
What I tried to do is to programmatically define a button inside a custom cell and try to append it when the numberOfRows is superior than the tableView items count. It results in a fatal error "Index out of range".
Here is what I'm trying to achieve :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let loadCell = itemList.dequeueReusableCell(withIdentifier: "loadMore", for: indexPath) as! LoadMore
let cell = itemList.dequeueReusableCell(withIdentifier: "normalCell", for: indexPath) as! ItemBox
if indexPath.row > itemArray.count {
return loadCell
}
return cell
}
I don't understand why I get this error as I specified one more row in the numberOfRowsInSection func.
I am having trouble making a table view with one static cell at the very top of my table view. This table view will hold 4 buttons and the rest of the views will hold a list of the user's songs.
I have already looked into other answers on here but all of them seem to be written in Objective C not swift.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sortedSongs.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RecentCell", for: indexPath) as! RecentCell
//cell.songTitle.text = albumList[indexPath.row]
//cell.songArtist.text = artistList[indexPath.row]
//cell.songImage.image = imageList[indexPath.row]
return cell
}
This is what I have been using to just set the regular table views. How would I go about modifying this code to allow for a static cell at the top and dynamic cells for the rest?
Don't use Static Cells. Choose Dynamic Prototypes in your table view and create 2 prototype cells.
And return first cell in first section, other cells in second section
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
} else if section == 1 {
return sortedSongs.count
} else if section == 2 {
return anotherArrayCount
}
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "FirstCell", for: indexPath) as! FirstCell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "RecentCell", for: indexPath) as! RecentCell
//cell.songTitle.text = albumList[indexPath.row]
//cell.songArtist.text = artistList[indexPath.row]
//cell.songImage.image = imageList[indexPath.row]
return cell
}
}
You can use the HeaderView of the table for that, just give your custom view to the . tableHeaderView property
Example:
override func viewDidLoad() {
super.viewDidLoad()
let myCustomView = MyCustomView()
tableView.tableHeaderView = myCustomView
}
Documentation: https://developer.apple.com/documentation/uikit/uitableview/1614904-tableheaderview
I have 2 prototype dynamic cell called InvoiceDetailCell and TotalCostFooterCell. I make the TotalCostFooterCell as the Footer Cell View using viewForFooterInSection. here is the code I use to assign data to the UITableView
here is my code in UITableViewController.
extension InvoiceDetailVC : UITableViewDataSource {
// MARK: - UI Table View Datasource Methods
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return invoiceElements.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "InvoiceDetailCell", for: indexPath) as! InvoiceDetailCell
cell.invoiceElementData = invoiceElements[indexPath.row]
return cell
}
}
extension InvoiceDetailVC : UITableViewDelegate {
// MARK: - UI Table View Delegate Methods
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "invoiceDetailFooterCell") as! TotalCostFooterCell
cell.totalCost = singleInvoiceData.unpaid
return cell
}
}
but the result is not as I expected, I mean the footer cell is stick / not move. here is the .gif file : http://g.recordit.co/vf0iwCfEWX.gif
you can see the total cost (red colour) is sticky / static, I want that footer cell can be scrolled and always on the bottom. or do I have the wrong to implement what I want?
make the table style to grouped
you can do it in two ways:
In viewDidLoad() do tableView.style = .grouped
Select the table view from storyboard and in the attribute inspector change the style to grouped. Please refer attached image.
Can't you just make it as the last row of the table view? I mean, the view is already a table view cell, so it makes sense to use it as the last row.
First change this:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return invoiceElements.count + 1
}
And then for cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == invoiceElements.count {
let cell = tableView.dequeueReusableCell(withIdentifier: "invoiceDetailFooterCell") as! TotalCostFooterCell
cell.totalCost = singleInvoiceData.unpaid
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "InvoiceDetailCell", for: indexPath) as! InvoiceDetailCell
cell.invoiceElementData = invoiceElements[indexPath.row]
return cell
}
You can set your custom view that you want by:
tableView.tableFooterView = yourCustomView
Or you can put everything inside your xib/storyboard like this:
Only those cell are displaying which are fitting on screen. if scrolled to next(offscreen) cell only white screen is displayed. it allows to scroll but only white space is displayed. Even the last row which was half displayed is also remains half only.
extension LiveTVController: UITableViewDataSource,UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 10
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let reuseIdentifier = tableView.tag == 1 ? ProgrammeListCell.reuseIdentifier : StreamListCell.reuseIdentifier
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)
if let cell = cell as? StreamListCell {
cell.programmeList.delegate = self
cell.programmeList.dataSource = self
}
return cell
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return tableView.tag == 2 ? 10 : 0
}
Now after scrolled down for next rows. there are total 10 sections returned and each section have 1 row.
Specify the height of cell according to cell type.And also place this video view in a table view header instead of using cell for first element.