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.
Related
I am currently working on a swift based HRM project. where it requires to show a tableview with slightly customized cell. cells it self containing two buttons, under some business logic one button would be hidden. for example ,
if the current user is the employee himself , he can see a list, the cell containing his name can see two buttons,but other cell would show simply one button.
i have tried the followings:
1. if the userId == employeeId (employeeId came from a model) then ,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ClaimTableViewCell", for: indexPath) as! ClaimTableViewCell
if(self.claimdata[indexPath.section].employeeId == self.empId) {
cell.CancelButton.isHidden = false
}
also , i have tried
if(self.claimdata[indexPath.section].employeeId != self.empId) {
cell.CancelButton.frame.size.height = 0
}
works fine for the first frame , the problem begins when i begin to scroll. for some unintended cell it also shows two buttons.
Am I missing something?
This issue is due to the cell reusability in UITableView.
Use below code in your cellForRowAtIndexPath method.
cell.CancelButton.isHidden = true
if(self.claimdata[indexPath.section].employeeId == self.empId) {
cell.CancelButton.isHidden = false
}
As tableView cell is reusableCell
dequeueReusableCell withIdentifier
you just need to give else condition so when it reuse the cell again it knowns what to do with CancelButton.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ClaimTableViewCell", for: indexPath) as! ClaimTableViewCell
if(self.claimdata[indexPath.section].employeeId == self.empId) {
cell.CancelButton.isHidden = false
}else{
cell.CancelButton.isHidden = true
}
}
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.
I am trying to implement a custom table view which has different types of cells: type A and type B. All of my cells should be of type A, except for one that will be of type B. Whenever the users selects a cell, this one changes to type B.
My code is the following one:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = indexPath.row
if (row == typeBCellIndex) {
// Get Type B cell
let cell = tableView.dequeueReusableCellWithIdentifier(typeBCellIdentifier, forIndexPath: indexPath) as! TypeBTableViewCell
return cell
} else {
// Get Type A cell
let cell = tableView.dequeueReusableCellWithIdentifier(typeACellIdentifier, forIndexPath: indexPath) as! TypeATableViewCell
cell.detailLabel.text = "I am a type A cell"
return cell
}
}
The variable typeBCellIndex is initialised in 0, and this code gives an error when I add a new cell and try to dequeue the cell at index 1.
In Objective-C, as this links indicates, I would check if the cell is nil, and if not create a new instance of the corresponding cell. However, I am not sure if this concept applies to Swift, and in case it does, I don't know how to do it.
declare a variable cellindex before viewdidload method and initialize to 3 or any number
and in tableview design two different cells and assign unique identifier for each
code for tableview is
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell!
var row = indexPath.row
if(row == cellindex){
cell = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! UITableViewCell
}else{
cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! UITableViewCell
}
return cell
}
the cellindex row will be cell2 and other cells are cell1
as you know tableViewCells can be displayed incorrectly after scrolling up and down, if you dont reset them in a certain way. After searching the internet without finding a satisfying answer, I would like to know how to do exactly that.
I am using one prototypeCell with an identifier that is reused. The titles and subtitles are currently stored in arrays. Depending on the indexpath, the specific string is taken from them. But how do i reset the content in a way, that the correct String is displayed? At the moment, the "incorrect" cell shows the title of the cell last initialised.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! UITableViewCell
let row = indexPath.row
cell.textLabel?.text = cellNames[row]
cell.detailTextLabel?.text = cellDetails[row]
return cell
Thank you for answering
In your cellForRowAtIndexPath: delegate method, reset ALL the modified properties of the cell before returning it. That's it.
I need to test if the value of a custom cell label is contained within an array. To achieve this I created a function that does the test and returns a boolean. My problem is that every time the cell enters the screen, the test is done again.
Where should I make the test so it is done only once ?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as CustomTableViewCell
var name:String = Array(self.contactList[indexPath.row].keys)[0]
var phones:String = self.contactList[indexPath.row]["\(name)"]!
cell.nameLabel.text = name
cell.phoneLabel.text = phones
cell.inviteButton.tag = indexPath.row
var (matched, id) = self.isRegistered(phones)
if(matched){
cell.phoneLabel.text = "TRUE"
cell.idUser = "\(id)"
}
return cell
}
I need to be able to modify the cell in response to this test. Thanks for your help !
Your test is called every time the cell appears because you a placed the test call inside cellForRowAtIndexPath: (If like you said you need to change the cell's label value according to the test result, I don't see any other choice)
You can try using the UITableViewDelegate methods
optional func tableView(_ tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
This will be called every time a cell needs to be presented.
Second way is a bit tricky and I don't recommend it, you can create a pool (array) of UITableViewCells and maintain (call test & change values) from that pool at a time you think is best (when scrolling the tableView for example)