I am trying to create a segue happen when a cell has been selected. I have tired using cell.dequeueReusableCellWithIdentifier(""). However it is returning "nil" whilst unwrapping. I have set up the cells ID correctly and they match. Any help is greatly appreciated!!
if menuTableView.dequeueReusableCellWithIdentifier("") == "logout" {
print("logout")
performSegueWithIdentifier("logoutSegue", sender: self)
}
Thanks in advance
There is a UITableView delegate method for when a user selects a cell, this is good for knowing when a user has selected a cell, but we need to identify if it is the logout cell that has been pressed.
To identify the cell we'll be setting the tag property of the your logout cell.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
//this is the indexPath row where we want our login cell to be showed
let loginCell = tableView.dequeueReusableCellWithIdentifier("login", forIndexPath: indexPath) as! LoginTableViewCell
//set the tag so when we select the cell we can see if the cell we have selected has a tag of 5
loginCell.tag = 5
return loginCell
}else {
//here goes our other cells, in this case they'll just be normal UITableViewCell
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
return cell
}
}
In our cellForRowAtIndexPath delegate method we'll instantiate the loginTableViewCell in the first row and set its tag to 5, if the row isn't 0 we simply return our normal cell
So now we have a cell where the tag is 5 and all the other cells do not have a default tag property of 0, now, when the user selects a cell we can check for this method in the didSelectRowAtIndexPath delegate method of our table view.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)!
if cell.tag == 5 {
//cell is login cell
//perform segue here
}
}
This delegate method gives us the table view and the indexPath of the selected cell. Now we call CellForRowAtIndexPath on the table view to get the cell that was selected. Now that we have the cell we can compare the cell's tag. If the tag is 5 the logout cell was selected so we can perform our segue there.
Related
I'm trying to get the indexPath of a tableView cell in the cell class.
I've got a collectionView inside the table view cells and I'm trying to make label inside the collectionView cell show the indexPath.row of the tableView cell that particular collectionView in.
Currently i have
var indexPathForCell: indexPath
in my cell class.
Then in the tableView class i have this in cellForRowAt indexpath
cell.indexpathForCell = indexPath
lbl.text = String(indexPathForCell.row)
If there is "3" or fewer tableView cells this works but if theres more then the 4th row then shows "0" as the indexPathForcell.row, and as I scroll in the collectionView the numbers then chnage from "0" to "3" and even show "1". Each cell then shows a different number as i scroll.
a simple solution for that is, in your viewController inside the collection cellForItemAt method gives the cell a tag like
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SignupSelectCourseCollectionViewCell", for: indexPath) as! SignupSelectCourseCollectionViewCell
cell.tag = indexPath.row
return cell
}
and now you can access tag property in cell class like
override var isSelected: Bool {
didSet {
let indexPathRow = self.tag
}
}
This question already has answers here:
Issue Detecting Button cellForRowAt
(3 answers)
Closed 5 years ago.
I have a tableview divide in section, I must to print the number of row and section when I tap the button in a cell. How can I get this?
Store the indexPath inside your cell and retreive it when the button is pressed.
Table view controller
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "custom") as! CustomTableCell
cell.indexPath = indexPath
return cell
}
Custom table cell
class CustomTableCell: UITableViewCell {
var indexPath: IndexPath!
#IBAction func buttonPressed() {
print(indexPath)
}
}
Implement the tableView:didSelectRowAtIndexPath: method. When it gets called, an NSIndexPath will be passed in that has the section and row properties on it.
This method will be called every time a tableview cell is pressed. The index path will be the index path of the cell that was pressed.
https://developer.apple.com/documentation/uikit/uitableviewdelegate/1614877-tableview
EDIT:
I misread the question. When the button is pressed, get the TableViewCell from the button by accessing the superview of the button. Then use the TableView's indexPathForCell method to get the indexPath of the button.
So I have a tableview that has a list of items in each cell. Each of these cells contain an image view which, upon being tapped, expands the cell and displays the image for that item. When I scroll down the table view and scroll back up to the cell that was selected, the image is gone. I know this is due to reusing cells but I'm not sure on how to keep the expanded cells image in place while scrolling through other items.
The closest I've come is here:
my table view reuse the selected cells when scroll -- in SWIFT
If someone could lend me a hand that would be awesome. Thanks!
Edit: Adding code snippets - Sorry for the wait.
fileprivate var expandedRowIndex: Int?
// cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// CatalogItem row.
let item = self.items[indexPath.row]
let expanded = indexPath.row == self.expandedItemRowIndex
// Return standard catalog item cell.
let reuseID = expanded
? CatalogItemCell.PROTOCELL_EXPANDED.id
: CatalogItemCell.PROTOCELL.id
let cell = tableView.dequeueReusableCell(withIdentifier: reuseID) as! CatalogItemCell
// Reset thumbnail image back to nil. Needed so that images appear
// only in the cell that they belong in.
if indexPath.row == self.expandedRowIndex{
cell.uiImage_Thumbnail.image = nil
}
return cell
}
// didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
// Expand row - Get the current cell and show image
self.expandedItemRowIndex = indexPath.row
let item = self.items[indexPath.row]
let currentCell = tableView.cellForRow(at: indexPath)
// Pass both the selected cell and item to the ImageManager
ImageManager.startImageRequest(currentCell: currentCell!, item: item)
if self.expandedRowIndex == indexPath.row
{
// Selected row is already expanded.
return
}
var reloadPaths = [IndexPath]()
// Collapse previously expanded row.
if let previousRowIndex = self.expandedRowIndex
{
reloadPaths.append(IndexPath(row: previousRowIndex, section: 0))
}
// Expand the selected row.
self.expandedRowIndex = indexPath.row
let item = self.items[indexPath.row]
debugPrint(item.description)
reloadPaths.append(IndexPath(row: indexPath.row, section: 0))
tableView.reloadRows(at: reloadPaths as [IndexPath], with: .fade)
}
You can maintain a selectedIndex variable.
In your cellForRow you check whether this call is for selectedCell. If yes, then do the customisation that is required for selected cell.
Also you might want to handle heightForRow, there also check whether the call is for selected cell.
You can maintain an indexPath for selected cell. If there are multiple sections.
No need to prevent it from getting reused.
Hope that helps.
I have two tables in a tableview in one UIViewController(Not UITableViewController). Now I want to let only one of the cells adding UITableViewCellAccessoryDisclosureIndicator to let users click for viewing another tableview.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if indexPath.section == 0{
cell.textLabel?.text = "\(rentTitle[indexPath.row]): \(rentArray[indexPath.row])"
}else{
cell.textLabel?.text = "\(cashflowTitle[indexPath.row]): \(cashflowArray[indexPath.row])"
}
return cell
}
There are 6 rows in the first table and 5 rows in the second one. I want to add the disclosureIndicator in the third row of the second table. So the questions are: 1. How to add the disclosureIndicator in the 3rd row of the second table? 2. How to make that row actively link to another tableView? Thanks a lot!
func tableView(tableView: UITableView,accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath){
var cell = UITableViewCell()
if indexPath.section == 1{
if indexPath.row == 2{
print(indexPath.row)
}
}
}
I tried the print first.
That arrow isn't a UINavigationItem; it's a UITableViewCellAccessoryDisclosureIndicator.
To add that UITableViewCellAccessoryDisclosureIndicator "arrow" to your cell's accessory view, add this line:
if indexPath.row == 2 { //Third row
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
}
And then to perform a specific action when that accessory view is tapped, implement
tableView:accessoryButtonTappedForRowWithIndexPath:
In this method implement your navigation by checking the indexPath again.
I have a UITableView with prototype cells that essentially takes up the whole page. I have a UIButton on the very bottom that should display a pop-up static UITableView when tapped. I'm struggling to account for the pop-up table view in cellForRowAtIndexPath.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let result: UITableViewCell
if tableView == self.tableView {
var cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = array[indexPath.row]
result = cell
} else if tableView == self.popUpTableView {
var popUpCell = self.popUpTableView.dequeueReusableCellWithIdentifier("popUpCell", forIndexPath: indexPath) as! UITableViewCell
popUpCell.textLabel!.text = popUpArray[indexPath.row]
result = popUpCell
}
return result
}
I'm getting an error at return result, where Variable 'result' used before being initialized, but I'm declaring it at the very top. Where am I going wrong with this?
You need to have exhaustive choices. It's possible that result never gets initialized because your checks are "if" and "else if". What happens if tableView is not either "self.tableView" or "self.popUpTableView"?
The simple fix is (if you only plan on having these two) to simply change your "else if" to a simple "else". This way result will always get initialized.