How do I remove a static table view cell by doing a if statement like this:
if ____ {
remove static cell
} else {
keep cell in tableview
}
The bolded part is what I need the code for. I searched the internet for an answer, but I could not find one. Thanks for the help! I'm using Swift 3
First, make sure to change cells to have Dynamic Properties, because static cells are hard-coded.
Second, you don't need an else statement. If the condition is true, delete the cell, otherwise do nothing. To delete a cell, use a function:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Cell deleted")
// delete any additional data from containers like arrays or dictionaries if needed
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
If this is a static tableview you can't remove a cell. If you attempt to you'll probably fall into all sorts of issues. Your best solution is to set the cell's height to zero and hide it.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt:indexPath)
if indexPath == cellToHide {
cell.isHidden = true
}
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == cellToHide {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
Related
I am using a UITableView and what I am doing is I am changing the color of the cell when I tap on the cell using didSelectRow function of UITableView at cellForRowAt. The thing which is bothering me is when I scroll down or scroll up, those cells whom I changed the color before were changed to other cells. Here is my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell
cell.backView.backgroundColor = .white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = myTableView.cellForRow(at: indexPath) as! TasksTableViewCell
cell.backView.backgroundColor = UIColor(named: "primaryViewColor")
}
Does anyone knows why this happens? Does anyone has a solution that when only those cells changes color whom I tap on, and when I scroll down or move up only those cells have the other color?
cellForRowAt will be called every time that cell is displayed.
you need selected list to save selected index.
var listSelected: [Int] = []
and
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell
cell.backView.backgroundColor = listSelected.contains(indexPath.row) ? UIColor(named: "primaryViewColor") : .white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if listSelected.contains(indexPath.row) {
listSelected = listSelected.filter{$0 != indexPath.row}
} else {
listSelected.append(indexPath.row)
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}
I encountered do you see the problem many times. Even if using and iVar can solve the problem, You are mixing "Controller" logic and "Model" logic.
I usually prefer to move "selection" state inside the model.
Suppose You have a class "Contact" you use to fill cell data (usual MVC pattern)
I add:
class contact{
..
var selected = false
}
AND in TV delegation method I use to apply selection, OR better I use a custom selection method in a custom cell (for example to see a √ element in cell)
As a bonus multiple selection come for free, and you can also save current selections for next run :)
So as I understand you select a cell and after that other cells look like they are selected?
If so I think this is happening because you change the background color of the cell and tableViews and collectionViews are reusing the cells, basically keeping the background you changed behind.
TableViewCells are reused as soon as they leave the visible area.
This means that a cell whose background you have colored will be deleted from the view hierarchy as soon as it is scrolled up or down. If the corresponding row is scrolled in again, the function cellForRowAt is called again for this IndexPath and the cell gets a white background.
The easiest is to save the IndexPaths of the selected cells and check in the cellForRowAt function if the current cell has to be selected.
Add the following var to the viewController class:
var selectedIndexPaths = Set<IndexPath>()
and modify the tableView delegate methods:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = myTableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell
cell.backView.backgroundColor = (selectedIndexPaths.contains(indexPath) ? UIColor(named: "primaryViewColor") : .white)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if selectedIndexPaths.contains(indexPath)
{
selectedIndexPaths.remove(indexPath)
}
else
{
selectedIndexPaths.insert(indexPath)
}
tableView.reloadRows(at: [indexPath], with: .none)
}
You can use
step 1: create model
class DemoModel {
var isSelected: Bool = false
var color: UIColor = .While
}
step 2: and in tableview
var listDemo: [DemoModel] = [DemoModel(),...]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier:
"TasksTableViewCell") as! TasksTableViewCell
var obj = listDemo[indexPath.row]
cell.backView.backgroundColor = obj.color
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var obj = listDemo[indexPath.row]
obj.color = UIColor(named: "primaryViewColor")
tableView.reloadRows(at: [indexPath], with: .automatic)
}
I want to delete an item from a table view.
First I added a filePath property on my class (that was missing)
Then I corrected the line of code to find the right filePath
the problem is solved but still I have the wrong file deleted so I check the sync of the arrays.
First, I make sure the table view knows what it shows and it appears the arrays are synced. I debug the code and I find that when I swipe to delete an item the code still deletes another file.
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableOfExpences.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CellOfExpencesTableViewCell
let myOneExpense = self.tableOfExpences[indexPath.row]
if myOneExpense.size != nil {
//Arrangement Of the cell
//allocate the right image for each segment
} else {
cell.nameCellLabel?.text = "No Cost"
}
return cell
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
self.tableOfExpences.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
print("the removed from the table expence is the \(String(describing: tableOfExpences[indexPath.row].expenseID))")
print("We had bought a \(String(describing: tableOfExpences[indexPath.row].note))")
In my case there was a numerous things why the wrong file was deleted but the most tricky(when all the code seemed to be correct) was that first the file must be removed from the directory and then the cell from the table.
So just reversing the order of lines so that first to delete data from the file
try FileManager.default.removeItem(atPath: paths[indexPath.row])
and then to implement the
self.tableOfExpences.remove(at: indexPath.row)
solved the last great problem.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if let cell = tableView.cellForRow(at: indexPath) as? ExpandablePlaneTableViewCell {
return 400.0
}
return 75.0
}
I want to change size of my cell but inside of heightForRowAt it cannot see my cell and crashed. When I put there if let check it does not enter inside of the block and just takes 75.
Can anyone tell me what the problem is? It's too strange for me!
I already set delegate to self. So it call the function but cannot detect my cell there.
UPDATE
In my ExpandablePlaneTableViewCell I have a variable:
var exapanded = false
Later in my ViewController: On click on the button in the cell I run my delegate method:
func expandViewButtonTapped(_ sender: ExpandablePlaneTableViewCell, for indexPath: IndexPath) {
sender.exapanded = true
tableView.reloadRows(at: [indexPath], with: .automatic)
}
and after I want to expand it and reload the cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "expandableCell", for: indexPath) as! ExpandablePlaneTableViewCell
cell.delegate = self
cell.indexPath = indexPath
return cell
}
Do not attempt to get a cell in heightForRowAt. And there certainly is no reason to do so in your case.
You seem to want the height to be one value for certain types of cells and another height for other types.
Simply use the same basic logic you have in cellForRowAt, based on the indexPath, to determine which height to return. In other words, base the decision on your data model, not on the cell.
I'm building an iOS app with a tableView, it's using a Realm database for the datamodel. When I try to delete a row by dragging the cell towards left, the section header follows the dragging movement to the left. When delete is pressed, the cell is deleted and the section header moves back into the right place.
Any clues to why the section header is moving with the cell?
The header cell is defined in the storyboard as a dynamic prototype cell, and the row cells are defined in a seperate xib and registered in the tableview. The section cell has the "Indent While Editing"-option unchecked in the storyboard.
The "Weekly report" is in the section header.
Here is the code I've implemented to enable editing:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
try! realm.write {
let reportToDelete = reportList[indexPath.row]
realm.delete(reportToDelete)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
}
I've tried both on the device and two different simulators, and with cleanin the build folder.
EDIT
The header is loaded from the storyboard, where it has a reuseable identifier: "WeeklyReportHeader", and the UIView in return by the tableView's delegate.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return tableView.dequeueReusableCell(withIdentifier: "WeeklyReportHeader")! as UIView
}
I think this has something to do with using a cell as the header, probably some issue to do with cell reuse.
To fix this, rather than using the cell itself (and casting it as a UIView for the header), use it's contentView property, which is a UIView anyways.
Eg
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return tableView.dequeueReusableCell(withIdentifier: "WeeklyReportHeader")!.contentView
}
SO I want to change the height of my UITableViewCell by doing something like this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedIndexPath = indexPath
tableView.beginUpdates()
tableView.endUpdates()
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath == selectedIndexPath {
return 140
} else {
return 90
}
}
However, the problem is that when I do this, the cell "expands" slower than the content of expanded portion shows, so whatever is in the expanded portion shows before the cell fully expands and it is kind of ugly. This problem can be fixed if I use tableView.reloadRowsAtIndexPaths(), but I don't want to reload the cell because I have a timer displayed in the expanded portion of the cell.