I have a UITableView show as below. All cells in the tableview can be edited except the last one.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if indexPath.row == tableView.numberOfRowsInSection(0) - 1 {
return false
}
return true
}
The first picture shows the tableview in normal mode; the second shows the tableview in editing mode. I do not want the last cell to be editable, so I return false in the function. But I do not want the last cell to appear when the tableview is in editing mode. How to do that?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.[TableViewName].dequeueReusableCellWithIdentifier("MainOfThecell") as? UITableViewCell
if [tableViewName].editing == true {
if cell.editing == false {
cell.hidden = true
}
}
return cell
}
Explanation :
[tableViewName].editing => This will return a bool on whether the tableView is in editing mode
cell.editing => This will return a bool on whether the cell is in edit editable state or not If the return is false then cell.hidden = true will hide the cell from the tableView.
NOTE:
When the user clicks in the button to edit the table execute [tableViewName.reloadData()] to force cellForRowAtIndexPath to be executed
If you want only the last cell to be hidden then check for the indexPath.row of the cell to determine it's position
Related
I have a tableView in which there is a section that is editable.
If I enable editing on the entire tableView, other cells while in editing mode are not selectable, so I need to enable the editing mode only on a specific section so that while other cells are selectable, the section is editable.
The reason that I need to set editing is those red square minus buttons that appear next to deletable cells.
Summary:
I need those red minus buttons next to cells, so I need to set editing as true, but if I do so, other cells won't be selectable thus I need to either set editing as true for a specific section, or add those red minus buttons without the editing mode.
You can implement canEditRowAtIndexPath method something like,
Obj-C
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 1) {
return YES;
}
return NO;
}
Swift :
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if indexPath.section == 1 {
return true
}
return false
}
To enable selection during editing you need to set,
Obj-C
self.yourTableView.allowsSelectionDuringEditing = YES;
Swift
self.yourTableView.allowsSelectionDuringEditing = true
Swift 4/5
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
if indexPath.section == 1 {
return true
}
return false
}
more nice to have like this
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return indexPath.section == 0 ? true : false
}
I'm new to iOS, swift. I have two sections in my tableView. I want to be able to do a longPressGesture on the second section, and not the first, enabling the user to reorder tableview cells in the second section. How would I do that in swift? Would anyone kindly provide a simple sample code in Swift?
Thanks for your help, much appreciated!
If you just want to reorder move the cell for the particular you may add some button/action to enable/disable reorder , there is delegate which you can use
Your code can be like this:
//enable editing in the tableview to true when you want to enable reorder in your case may on the UILongPressGestureRecognizer action
//In viewDidLoad()
tblView.editing = true//set it to false to complete the reorder
The delegate methods can be use like this:
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.None
}
func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
//get the reorder change in the path, you can do operation on the array
let itemToMove:String = arrData[fromIndexPath.row]//get the old path of item
arrData.removeAtIndex(fromIndexPath.row)//remove item from old path
arrData.insert(itemToMove, atIndex: toIndexPath.row)//at item at new path in array
}
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
//write code to allow reorder in the particular section/indexpath
if indexPath.section == 0 {
return false
} else {
return true
}
// Return false if you do not want the item to be re-orderable.
}
func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
//check if the reorder is allow in the particular section/indexpath before the reorder is done, return the old path if you don't want to move at Proposed path
if sourceIndexPath.section != proposedDestinationIndexPath.section {
return sourceIndexPath
} else {
return proposedDestinationIndexPath
}
}
the UILongPressGestureRecognizer can be implemented on the tableview or the tableview cell based on the requirements
let longpress = UILongPressGestureRecognizer(target:self, action:#selector(HomeScreenTableViewController.longPressGestureRecognized))
tblView.addGestureRecognizer(longpress)
func longPressGestureRecognized() {
NSLog("Detected")
tblView.editing = true
}
or in tableview cell with same method as above
let longpress = UILongPressGestureRecognizer(target:self, action:#selector(HomeScreenTableViewController.longPressGestureRecognized))
cell.addGestureRecognizer(longpress)
I have a tableview controller that I am using as a preferences screen. It has three sections, each with static cells.
The third section has 6 rows and each row represents a different date format, but depending on the device, not all appear when the view loads.
I am using the checkmark accessoryType to denote whether or not the particular option has been selected. (I get that from my Realm database store)
In the tableview in IB, I set all cells to have accessoryType - .None so initially, no checkmarks.
When the view appears, I retrieve the stored value and set the appropriate checkmark like this.
for (index,selDateFormat) in dateFormats.enumerate() {
if selDateFormat == dateFormat {
tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 2))?.accessoryType = .Checkmark
} else {
tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 2))?.accessoryType = .None
}
}
It works great if the row is in view so on an iPhone 6 plus, I am great. However, on an iPhone 4s, only the first two rows are shown in this section until I scroll. The problem is that if I selected an option in rows 3 - 6, the checkmark is not displayed because it was out of view when the view appeared.
Is there a way that I can get the checkmark to show when the view appears?
For those rows which are off screen, cellForRowAtIndexPath will return nil. You need to set the checkmark (or not) when the cells are created as the rows are scrolled on screen. Override cellForRowAtIndexPath and set the checkmark as required:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
if let selDateRow = dateFormats.indexOf(selDateFormat) {
if (indexPath.row == selDateRow) {
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}
} else { // just in case selDateFormat isn't in the dateFormats array...
cell.accessoryType = .None
}
return cell
}
Turns out the answer was even simpler in code
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
let section = indexPath.section
if section == 2 {
if dateFormats[indexPath.row] == dateFormat {
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}
}
return cell
}
I want to change the image in a custom UITableViewCell, depending on whether it is selected or not.
So, when user selects a row, the image in two rows has to be changed (both the current selected and the one to be selected).
Calling reloadData, or reloadRowsAtIndexPaths from didSelectRowAtIndexPath doesn't work because it deselects the current selected row, which I don't want to happen.
Calling reloadData from willDeselectRowAtIndexPath and willSelectRowAtIndexPath also causes the same problem.
Anyone know a solution for this?
Did you try just programmatically selecting the row in cellForRowAtIndexPath based on a stored property indicating the selected row?
I would an approach where you still use reloadData, or reloadRowsAtIndexPaths from didSelectRowAtIndexPath but first save the selected row in a property so that you can manually set it as selected when the cell is redrawn.
For example:
var selectedRow:NSIndexPath? = nil
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath
tableView.reloadData() // or reload a specific row
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TableViewCellReuseIdentifier")
if (indexPath == selectedRow) {
cell!.selected = true
} else {
cell!.selected = false
}
}
I have a feature in my app that allows users to tap on a table view cell and it will expand to show more information. This works great but there are a few issues:
1) When I segue away from the table view, the top cell becomes expanded.
2) When I tap to expand a cell and then tap again to shrink the cell, it loses the dividing line above it until I tap a different cell.
3) When I slide to delete, the content in the expanded version of the cell overlaps the cell below it like this:
Here is my code for expanding the cell:
var selectedRowIndex: NSIndexPath = NSIndexPath(forRow: -1, inSection: 0)
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRowIndex = indexPath
tableView.beginUpdates()
tableView.endUpdates()
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if tableView != self.searchDisplayController?.searchResultsTableView {
if indexPath.row == selectedRowIndex.row {
if cellTapped == false {
cellTapped = true
return 141
} else {
cellTapped = false
return 68
}
}
}
return 68
}