Deselect cell only if other cell in section is tapped - swift

I have a table view with two sections. Each cell in section 1 (the second section) has a tap accessory and a deselect method for when another cell in section 1 is tapped. However, if any cell in section 0 is tapped this also deselects the current selected cell.
My code is:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(indexPath.section == 1)
{
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark
}
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
if(indexPath.section == 1)
{
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None
}
}
I would only like the cells to be deselected if any other cell in section 1 is selected and ignore deselect for any other section.
Any thoughts?

For proper Reference, you need manage the reference in your globalArray itself, as shown below:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
.........
if ( globalArray[indexpath.row][SELECTED_STATE] == SELECTED )
{
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark
}
else
{
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None
}
.........
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//remove the pre selected state if needed by iterating the array
globalArray[indexpath.row][SELECTED_STATE] = SELECTED
tableView .reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}

Related

Hide button in another cell when cell is tapped

I have a `tableView with three cells. In two of them I have a button. I would like to hide the button in the other cell, when one of the cells is tapped.
I have tried some solutions in didSelectRowAt but have not been able to hide the buttons:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 1 {
if let cell = tableView.cellForRow(at: indexPath) as? ComposeCell1 {
cell.compose.isHidden = true
if let cell2 = tableView.cellForRow(at: indexPath) as? ComposeCell2 {
cell2.compose.isHidden = true //I can reach the cell from here, but its not hiding the button
}
}
} else if indexPath.row == 2 {
if let cell = tableView.cellForRow(at: indexPath) as? ComposeCell2 {
cell.compose.isHidden = true
}
}
}
Try to track the index for the pressed button with a variable. And use the variable in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell to update the button's visibility. Only thing you need to do in didSelectRowAt is assign the index value the variable and reload the table view
var selectedIndex: Int?
....
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedIndex = indexPath.row
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
.....
cell.compose.isHidden = indexPath.row != selectedIndex
.....
return cell
}

Table view cell accessory not changing when out of view

I have this piece of code:
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if let selected = self.lastSelected {
tableView.cellForRowAtIndexPath(selected)?.accessoryType = .None
}
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.Checkmark
self.lastSelected = indexPath
I allows me to place a checkmark on the cell that I select and removes the previous checkmark. The problem I am having is that if the list is large and the cell is out of view, the checkmark is not removed when a new cell is selected.
I have tried adding tableview.reloaddata() but that did nothing.
Thoughts?
cellForRowAtIndexPath returns nil for non-visible cells.
To get a radio button like effect, you need to do something like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
configureCell(cell, atIndexPath: indexPath)
return cell
}
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
if indexPath == selectedIndexPath {
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedIndexPath = indexPath
// Note indexPathsForVisibleRows may be nil depending on your app's content.
// zip just joins two arrays together, into a single array of tuples.
zip(tableView.indexPathsForVisibleRows!, tableView.visibleCells).forEach({ indexPath, cell in
configureCell(cell, atIndexPath: indexPath)
})
}

UITableView - Multiple selection AND single selection

I have 2 sections in my UITableView.
I want the first section to allow multiple cell selection and the second section to allow only single selection.
I tried some code but didn't work very well.
Code in swift if possible. Thank you.
You can simply try this. This solution works for me perfectly. Give it a try maybe worked for others...
Swift-4
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
}
}
else {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
}
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if indexPath.section == 1 {
if let cell = tableView.cellForRow(at: indexPath as IndexPath) {
cell.accessoryType = .none
}
}
}
Perhaps you could implement the table view's delegate methods:
tableView(_:shouldHighlightRowAtIndexPath:)
and
tableView(_:didSelectRowAtIndexPath:)
...and determine (from indexPath.row and indexPath.section) if the relevant section supports single/multiple selection (this will depend on your data model's custom logic -e.g.: "Section 0 supports multiple selection but section 1 does not"), and if it only supports single selection, check whether there is already a row selected (by accessing tableView.indexPathsForSelectedRows).
If there is a selected row already, you can:
Return false from tableView(_:shouldHighlightRowAtIndexPath:), and
Do nothing (just return) from tableView(_:didSelectRowAtIndexPath:) (I'm not sure if this method is actually called when you return false from shouldHighlight..., so perhaps check it).
This is easily achievable in two lines as follows: (Swift 4)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if sectionAllowsMultipleSelection {
if let indexPathsInSection = tableView.indexPathsForSelectedRows?.filter ({ $0.section == indexPath.section && $0.row != indexPath.row }) {
for selectedPath in indexPathsInSection {
tableView.deselectRow(at: selectedPath, animated: false)
}
}
}
}
If you want the selected row in section 2 to be the new selected row, this might work for you. Else, go with #NicolasMiari's answer.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.section == 1 {
for i in 0..tableView.numberOfRowsInSection(indexPath.section) - 1 {
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: i, inSection: indexPath.section))!
if (i == indexPath.row) {
cell.accessoryType = .Checkmark
cell.selected = false
}
else {
cell.accessoryType = .None
}
}
}
else {
//Do whatever for the first section
}
}
Not very elegant, but hopefully it will give you an idea.

Apply an IBAction only to a single cell

I have a tableView with prototypes cell; with this func I set cell height
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return cellHeight
}
with this action I change cell height touching up inside the UIButton
#IBAction func changeCellHeight(sender: UIButton)
{
if cellHeight == 44
{
cellHeight = 88
} else {
cellHeight = 44
}
tableView.beginUpdates()
tableView.endUpdates()
}
Now I need to change height only for selected cell (not for every cells); so I define
var index: NSIndexPath! and I implement this func
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
index = self.tableView.indexPathForSelectedRow()!
println("Cella " + "\(index)")
}
As I expected in console Xcode prints the selected cell (<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0} ).
So my trouble is how to use var index in the IBAction.
Thanks in advance.
To change your height based on selection, you don't need an IBAction if you are already implementing the didSelectRowAtIndexPath method.
Just make a little change in your didSelectRowAtIndexPath method first-
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
// You don't need to do this -> index=self.tableView.indexPathForSelectedRow()!
index = indexPath;
println("Cella " + "\(index)")
tableView.beginUpdates()
tableView.endUpdates()
}
And then a little change to your heightForRowAtIndexPath method-
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
if index == indexPath {
return 88
}
else{
return 44
}
}

Swift - Reorder UITableView cells

I do know that it's not too hard to do it in objective C , the problem is I'm learning Swift by skipping Objective C.
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/ManageReorderRow/ManageReorderRow.html
However is there anything equivalent to the link above in Swift?
I have tried this...here is the code
In my example code there is button that starts the editing ---
Action Method of the button -->
#IBAction func editTableView (sender:UIBarButtonItem)
{
if listTableView.editing{
//listTableView.editing = false;
listTableView.setEditing(false, animated: false);
barButton.style = UIBarButtonItemStyle.Plain;
barButton.title = "Edit";
//listTableView.reloadData();
}
else{
//listTableView.editing = true;
listTableView.setEditing(true, animated: true);
barButton.title = "Done";
barButton.style = UIBarButtonItemStyle.Done;
//listTableView.reloadData();
}
}
And the related UITableView delegate methods -->
// The editing style for a row is the kind of button displayed to the left of the cell when in editing mode.
func tableView(tableView: UITableView!, editingStyleForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCellEditingStyle
{
if (false == self.editing && !indexPath){
return UITableViewCellEditingStyle.None;
}
if (self.editing && indexPath.row == countryList.count){
return UITableViewCellEditingStyle.Insert;
}
else{
return UITableViewCellEditingStyle.Delete;
}
//return UITableViewCellEditingStyle.Delete;
}
// Update the data model according to edit actions delete or insert.
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!)
{
if editingStyle == UITableViewCellEditingStyle.Delete{
countryList.removeAtIndex(indexPath.row);
self.editTableView(barButton);
listTableView.reloadData();
}
else if editingStyle == UITableViewCellEditingStyle.Insert{
countryList.append("New Country");
}
}
// Determine whether a given row is eligible for reordering or not.
func tableView(tableView: UITableView!, canMoveRowAtIndexPath indexPath: NSIndexPath!) -> Bool
{
return true;
}
// Process the row move. This means updating the data model to correct the item indices.
func tableView(tableView: UITableView!, moveRowAtIndexPath sourceIndexPath: NSIndexPath!, toIndexPath destinationIndexPath: NSIndexPath!)
{
let item : String = countryList[sourceIndexPath.row];
countryList.removeAtIndex(sourceIndexPath.row);
countryList.insert(item, atIndex: destinationIndexPath.row)
}
You can also download full code Here
All the same rules apply as in Objective-C. You set the table view data source and delegate just like you would in Objective-C.
func tableView(tableView: UITableView!, canMoveRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true // Yes, the table view can be reordered
}
func tableView(tableView: UITableView!, moveRowAtIndexPath fromIndexPath: NSIndexPath!, toIndexPath: NSIndexPath!) {
// update the item in my data source by first removing at the from index, then inserting at the to index.
let item = items[fromIndexPath.row]
items.removeAtIndex(fromIndexPath.row)
items.insert(item, atIndex: toIndexPath.row)
}
If you need finer grain control, you can also implement
func tableView(tableView: UITableView!, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath!, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath!) -> NSIndexPath! {
…
}
Now there is a library for this reorder function: LPRTableView.
Converted Above Answer methods in Swift 3.0
// Determine whether a given row is eligible for reordering or not.
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
// Process the row move. This means updating the data model to correct the item indices.
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item : Dictionary<String, Any> = arrInterval[sourceIndexPath.row]
arrInterval.remove(at: sourceIndexPath.row)
arrInterval.insert(item, at: destinationIndexPath.row)
}