Restrict dragging onto specific section - ios

I want to restrict dragging option onto specific section in a single table view. Now I enabled dragging option onto just single section in specific section but what happened when use move successfully cell onto other section where dragging not enabled so it shouldn't move to that section where dragging is not enabled. Kindly see attached image where I enable editing for deleted in first section and dragging for section section and row shouldn't able to move onto first section. I want to perform this in single cell. Is this possible if yes then how?
This will be great for me. Thanks in advance.

Use targetIndexPathForMoveFromRowAtIndexPath::. It's a UITableViewDelegate method that will allow you to intercept the index path that the user is attempting to drag the cell to. If the section is somewhere that you don't want them to be able to drag the cell, simply return the source index path, and upon release, the cell will bounce back to its original position.
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
if (proposedDestinationIndexPath.section == sectionYouDontWant) {
return sourceIndexPath;
}
return proposedDestinationIndexPath;
}

Related

Can I use both UITableViewCellEditingStyleInsert and UITableViewCellEditingStyleDelete two button together?

I return canEditRowAtIndexPath is YES. If I swipe left, I can see the delete button and implement my delete action. How can I do if I swipe left, both insert button and delete button appear together?
I know there is a way, I should have a custom cell with two button on the right and just add a panGesture to recognize the swipe action. But I want to use Apple provide for us to do such easy work. Just can see insert and delete button together when I swipe the cell left? My apology for my poor expression.
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(editingStyle==UITableViewCellEditingStyleInsert)
{
NSLog(#"click insert");//I only have delete button, I also want to have insert button .
}
if(editingStyle==UITableViewCellEditingStyleDelete)
{
NSLog(#"click delete");
}
}
I know tableView:editActionsForRowAtIndexPath can do this job … But it is provide for IOS8.0 and later,,How to do for IOS7
At least as of iOS 8 this can't be done (I don't know if this changed in iOS 9). A cell can only have one of the 3 possible editing styles - None, Insert, or Delete. UITableViewCell does not support both Insert and Delete at the same time. When the table is in editing mode, the cell will show either no button, an insert icon on the left, or the delete icon on the left based on the row's single editing style.
It actually makes no sense to have both insert and delete on the same row. What does that mean for the user? Normally a table view would only have a single row (per section) that might have the insert editing style. This row, when tapped, allows the user to add a new row to the table view. Other existing rows might have the delete editing style to allow the user to delete that specific row.
So again, what would it mean for a single row to have both insert and delete editing styles?

showing and hiding a specific cell type in a UITableView (possibly with animation)

I have a UITableView and have seen this effect and would like to implement it for our the followind data:
menu_header
menu_subheader
* item
* item
menu_subheader
* item
* item
* item
Basically, I would like to show just the header and subeaders and then when the user clicks one of the subheaders, it displays the items (preferably in an animation block) AND adjusts the other cells down or up appropriately. Like this:
Is there a prebuilt component that does this? Thinking about it, it seems like I would like to set these item cells to be hidden. I have seen this https://github.com/peterpaulis/StaticDataTableViewController but it looks like it doesn't work with dynamic data. It seems like this should be really simple. Any ideas on how to get this done? Ideally, I'd like it to be able to when you click it insert the data and then if you click another sub-header, close the other one and add to that sub-header.
To implement "folding" in a table view you have two options:
Control the number of cells in a section based on a folded/unfolded property per section. When folding or unfolding, use the insert or deleteRowsAtIndexPaths:withRowAnimation: methods on the tableView.
Control the height of the cells using the delegate method. Return zero for folded sections based on a folded/unfolded property per section. When folding or unfolding, call beginUpdates followed immediately by endUpdates to re compute the heights and animate to the new layout.
I've created a simple implementation of the second option in this GitHub repo. Please let me know if you have other questions about it.
You have to remove and insert cells into your table view instead of hacking their height.
We use a controller for table views that lets you "hide/show" cells while actually handling the removal/reinsertion of rows in the table view.
The way "Toggle Details" works on the Demo is pretty similar to what you are trying to achieve:
- (IBAction)toggleDetails:(id)sender
{
// Hide if all hiddeable rows are hidden, show all otherwise
[self.topSection setObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]
hidden:(![self.topSection isObjectAtIndexHidden:1] &&
![self.topSection isObjectAtIndexHidden:2] &&
![self.topSection isObjectAtIndexHidden:3])];
}
Changing the height of cells to "hide" them is not optimal as the delegate will be asked for their sizes many times and cells will still be instantiated and configured yet not visible.
The sample library keeps the row data on memory (one object per row) while reusing cells. This should be ok for most projects, but maybe in your case not only all objects shouldn't be on memory but also you shouldn't fetch all of them at once.
Make your header will be Tableview Section and sub header will be Row...
And in didSelectRow delegate method insert rows, that will be your items.
There is a sample code from Apple that can help you in get this result.
The main difference is that in the Apple sample code is the header that triggers the action and shows the relative subviews, but this is not a blocking issue.
You can use normal cells to achieve that, by inserting and deleting rows while selecting one of them.
What is important is that you need to to remap datasource information or pair the info with another collection to get the state of that cell: opened or closed and subheader or item to identify them and choose the right action while selecting it.
Also important is to keep consistency between your data model(data source) and the number of cells, if you do using batch operation to ad insert and remove cells would not be a problem. If you don't you are going to see a lot of exceptions.
Take a look also here.
I actually wanted to just add a comment, but reputation issues...
Anyway, my personal favorite way of expanding/collapsing UITableView sections is described in this post: https://stackoverflow.com/a/1941766/2440562
If I am understanding the issue correctly, the menu_headers and menu_subheaders would always be visible and only the items would be shown/hidden.
So here it is my idea (let's see if I can explain it well enough):
You probably have an idea how many menu_subheaders you would have for each menu_header (static count or the number of elements of an array), so you can add one section for each menu_header (which would actually contain only one row or header) and in-between those you can add the expandable sections (menu_subheaders), which can be managed as shown in the answer I mentioned above. And as you want to collapse the previously expanded menu_subheader when tapping on another, you could just reset its boolean value and reload both with the reloadSections method. You would have to do some calculating for the placement of the menu_headers and menu_subheaders, but basically you wouldn't have to deal with cell heights and row insertions and deletions (that actually is my favorite part).
Here it is a quick code snippet of the calculations I've mentioned (not tested, totally improvised):
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return <number_of_menu_headers> + <number_of_menu_subheaders>;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
// handle first menu_header
} else if (indexPath.section < 1 + <number_of_menu_subheaders1>) {
if (indexPath.row == 0) {
// handle the menu_subheader header row
} else {
// handle the rest of the items
}
} else if (indexPath.section == 1 + <number_of_menu_subheaders1>) {
// handle second menu_header
} else if (indexPath.section < 2 + <number_of_menu_subheaders1> + <number_of_menu_subheaders2>) {
if (indexPath.row == 0) {
// handle the menu_subheader header row for the current menu_subheader
} else {
// handle the rest of the items for the current menu_subheader
}
} etc...
}
Again, just an idea...

How to know that no row is selected in my UITableView?

I use a UITableView to display a list of items, and when a row is selected I show that item in a detail view next to it (using a split view controller).
As the selection in the table view changes I want my detail view to change as well, which is of course standard behavior and it works flawlessly... except when no row is selected anymore in the table view.
Users can for example delete a row from the table view, and during and also after that deletion there will be no selected row in the table view. Of course after a row is deleted I let my detail view controller know, but during the editing process in the table view, when no row is selected, my detail view controller does not know this.
I tried to use the UITableViewSelectionDidChangeNotification but that only gets sent when the user selects a different row, not when a deselection occurs.
How can I be notified of the fact that the table view switches from having a row selected to having no selection at all?
EDIT:
As a temporary solution, I tried renaming the Edit-button to "Reorder" and only allowing moving rows from A to B but without allowing the deletion controls, but this can not be done, there is no move control without enabling editing on a row. The thing is, I do get a pointer to a row that is up for moving, so I can keep that selected. I do not get this pointer for a row up for deletion, so no go for me. I always want to know what row a user works on, and keep that row selected at all times.
I may have to resort to ditching the standard editing behavior and adding my own buttons and methods for it. Or see what gestures can do for me to capture touches on any row...
There is a property indexPathForSelectedRow. I'm not sure what it would return when there is no selected row, but it may return nil or something like that, which you could use as a trigger to know if there are any rows selected. Something like
if (myTable.indexPathForSelectedRow == nil)
{
//do something here to account for no rows being selected
}
else
{
//do stuff here to set up your detail view
}
Let me know if this works for you.
How are you implementing the deletion of rows? Are you implementing the following data source method?
tableView:commitEditingStyle:forRowAtIndexPath:
You can have a property like
NSIndexPath *selectedIndexPath
and set it to nil when a row is being deleted.
Example:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//select another row in your table
[tableView selectRowAtIndexPath:*indexPathOfTheRowToBeSelected* animated:YES scrollPosition:UITableViewScrollPositionNone];
//then delete row from data source
}
The method above will be called when the user touches the delete button on the table he/she has selected to delete.
Okay I misread what you were asking at first, I'm pretty sure what you want is either – tableView:willDeselectRowAtIndexPath: or – tableView:didDeselectRowAtIndexPath:. These methods will be triggered automatically when the user deselects a row (either right before the row is deselected or right after, respectively). Implement one of these in your table view delegates code, and you'll know whenever a row gets deselected, and you can put your code to select the next row or whatever you want in one of these methods.
I struggled with this as well. Turns out that when the "Edit" button is hit, all rows are deselected at that point. You can override setEditing:animated: to detect when it is hit, but you must call [super setEditing:editing animated:animated] before you return.
See this link for where I found this:
How can i identify self.editButtonItem button's clicked event?

Button Displays Under Cells in Custom UITableViewCell

I have an app that uses a custom UITableViewCell to display detail information after a user clicks on a given row in a table. I can't seem to figure out why the "Reply" button located in the cell is inactive and appears behind the table itself. I can't click on it, select it, or do anything. I used Interface Builder to add the button rather than programmatically add it.
I've tried changing a number of things including the cell's class and File's Owner, but can't seem to get the button to be active and working. I think the button is linked up properly with a connection to a method in the code.
Here's a minimal, complete example of the code:
https://www.dropbox.com/s/atcof58ciqbaojr/CustomCell.zip
Apparently I needed to tell the table view how high the cell was. This is what fixed it:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
return 157.0;
}

Changing UITableView functionality on button press

I'm trying to figure out the best way to do this - I have a UITableView of items which the user has previously selected and which is stored. When you click an item it takes you to a detail page. What I need is to be able to click a button below the table view which reloads the table and changes the accessory so its a tick instead of a disclosure, then the user can un-tick the items and remove them from the list, before clicking another button which reloads the updated table and restores the disclosure accessory.
Question is, what is the best way to "remember" which way to handle the table reload after the click so it knows which way to display it? Would you use the NSUserDefaults to store a flag on the button click or is there a more elegant way to do it? I guess I could use the status of the button, whether it's in one state or another, but I'm guessing there is something in-built I'm missing.
Hope that makes sense - thanks.
Usually I have some 'model object' and depending on array of those objects I construct table. My cellForRowAtIndexPath looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
InterestsCell *cell = (InterestsCell*)[tableView dequeueReusableCellWithIdentifier:kInterestsCellID];
if (cell == nil) {
...
}
Interest *i = (Interest*)[self.interestsArray objectAtIndex:indexPath.row];
cell.myTfSubview.enabled = i.isChecked;
return cell;
}
If you don't have your model then you can create array of BOOL values and store flags there.

Resources