I read the documentation about how to manage deletion and reordering of rows in a UITableView. I created the edit button and I'm able to delete rows. I would like the user to be able to reorder the rows as well. It seems simple, but I can't understand how to tell the cells that they can be moved.
To tell the rows they can be deleted I use the editingStyleForRowAtIndexPath, but how do I tell the cell it can also be moved and where do I set the showsReorderControl? I tried to place in cellForRowAtIndexPath, but nothing is shown.
Thanks!
You have to say that rows can be moved:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
and implement this delegate to update your data source:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
See Managing the Reordering of Rows of Table View Programming Guide for iOS
In my case I have implemented all the required UITableViewDelegate methods as mentioned in the Apple document and in the answers here, but still cannot see the reorder control. Eventually I found out it's because I overrode the layoutSubviews method without calling the super's default implementation. After I added the [super layoutSubviews], my reorder control finally appears.
The reason why we need to call [super layoutSubviews] is because when we toggle the table's editing property it would call the cell's layoutSubviews method, and the system provided controls such as the reorder control is displayed within UITableViewCell's default layoutSubviews method. Once you realize this you can also modify your layoutSubviews implementation to change the appearance of your cell depending on whether it is being edited or not to make it less clumsy when the reorder control appears.
So here is a checklist for the row reordering:
make sure the delegate methods tableView:canMoveRowAtIndexPath and tableView:moveRowAtIndexPath:toIndexPath are implemented
make sure the tableView's editing property is set to YES
If you have a custom UITableViewCell, make sure you call
[super layoutSubviews] if you override this method
Adding to #benoit answer above. If your model happens to be a mutable array, something like this would suffice for the tableView:moveRowAtIndexPath:toIndexPath:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
id objectToMove = [_objects objectAtIndex:fromIndexPath.row];
[_objects removeObjectAtIndex:fromIndexPath.row];
[_objects insertObject:objectToMove atIndex:toIndexPath.row];
[tableView reloadData];
[self saveObjects]; // A method of your own to make new positions persistent
}
try this . . .this will handle arranging and updating of cell in case of simple tableview
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
[tableData insertObject: [tableData objectAtIndex:sourceIndexPath.row] atIndex:destinationIndexPath.row];
[tableData removeObjectAtIndex:(sourceIndexPath.row + 1)];
}
Related
I want change the cells order in my tableview
I am using following code
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
[tableView moveRowAtIndexPath:path1 toIndexPath:path2];
}
here path1 indexpath of row which user selected now I want find the indexpath of the row the user drop that cell so how can I find that toIndexPath(path2).
I think you're confused with the purpose of this method - this is a callback function of the UITableViewDataSource that's designed to notify the data model of changes in the table. From the docs:
Tells the data source to move a row at a specific location in the table view to another location.
The UITableView object sends this message to the data source when the user presses the reorder control in fromRow.
This means that what you need to do here is to make sure your model (Usually an array) is rearranged to sync properly with these changes.
Hope this gives you a good direction.
You should implement:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
& also:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
//do whatever you want after the row has been moved
}
Here is an example of drag N drop:
https://github.com/coderDove/UITableView-Drag-n-Drop
Hope this Helps!!!
I am making an app in which I want to move the row.So I can do it by
[self.tableList setEditing:YES animated:YES];
where "tableList" is my table's name but whenever I am running this line.I am not able to get the icon for move which usually comes at right side for moving a cell instead I am getting the icon to delete a row which comes on left side of a cell.
Please help me to get my cell move and ask if you need any clarification of my question..
Thanks.
You need to implement the below two methods
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
//do code according to your requirements of app
//if you do not write ant thing in the method then also your row will be moved.
NSString *stringToMove = [[self.dataArray objectAtIndex:sourceIndexPath.row] retain];
[self.dataArray removeObjectAtIndex:sourceIndexPath.row];
[self.dataArray insertObject:stringToMove atIndex:destinationIndexPath.row];
[stringToMove release];
[tableView reloadData];
}
use this link of aple and scrol down to apple how to move or scrol rows. cheerz :)
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableView_Class/Reference/Reference.html
– beginUpdates
– endUpdates
– insertRowsAtIndexPaths:withRowAnimation:
– deleteRowsAtIndexPaths:withRowAnimation:
– moveRowAtIndexPath:toIndexPath:
– insertSections:withRowAnimation:
– deleteSections:withRowAnimation:
– moveSection:toSection:
– scrollToRowAtIndexPath:atScrollPosition:animated:
– scrollToNearestSelectedRowAtScrollPosition:animated:
use these two method for row move
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath*)indexPath
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
In my app I need to delete multiple rows in a table, edit the table and get a check box beside the table. When checked then the table cells are deleted. It is like the iPhone message app. How can I do this, please help me.
If I understand your question correctly, you essentially want to mark UITableViewCells in some way (a checkmark); then, when the user taps a master "Delete" button, all marked UITableViewCells are deleted from the UITableView along with their corresponding data source objects.
To implement the checkmark portion, you might consider toggling between UITableViewCellAccessoryCheckmark and UITableViewCellAccessoryNone for the UITableViewCell's accessory property. Handle touches in the following UITableViewController delegate method:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *c = [tableView cellForRowAtIndexPath:indexPath];
if (c.accessoryType == UITableViewCellAccessoryCheckmark) {
[c setAccessoryType:UITableViewCellAccessoryNone];
}
//else do the opposite
}
You might also look at this post regarding custom UITableViewCells if you're wanting a more complex checkmark.
You can set up a master "Delete" button two ways:
The IB approach
The programmatic approach
In either case, eventually a method must be called when the master "Delete" button is pressed. That method just needs to loop through the UITableViewCells in the UITableView and determined which ones are marked. If marked, delete them. Assuming just one section:
NSMutableArray *cellIndicesToBeDeleted = [[NSMutableArray alloc] init];
for (int i = 0; i < [tableView numberOfRowsInSection:0]; i++) {
NSIndexPath *p = [NSIndexPath indexPathWithIndex:i];
if ([[tableView cellForRowAtIndexPath:p] accessoryType] ==
UITableViewCellAccessoryCheckmark) {
[cellIndicesToBeDeleted addObject:p];
/*
perform deletion on data source
object here with i as the index
for whatever array-like structure
you're using to house the data
objects behind your UITableViewCells
*/
}
}
[tableView deleteRowsAtIndexPaths:cellIndicesToBeDeleted
withRowAnimation:UITableViewRowAnimationLeft];
[cellIndicesToBeDeleted release];
Assuming by "edit" you mean "delete a single UITableViewCell" or "move a single UITableViewCell," you can implement the following methods in the UITableViewController:
- (void)viewDidLoad {
[super viewDidLoad];
// This line gives you the Edit button that automatically comes with a UITableView
// You'll need to make sure you are showing the UINavigationBar for this button to appear
// Of course, you could use other buttons/#selectors to handle this too
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//perform similar delete action as above but for one cell
}
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
//handle movement of UITableViewCells here
//UITableView cells don't just swap places; one moves directly to an index, others shift by 1 position.
}
You can put 1 UIButton lets call it "EDIT" and wire up it to IBAction. In IBAction write so you will be able to do as per your requirement.
-(IBAction)editTableForDeletingRow
{
[yourUITableViewNmae setEditing:editing animated:YES];
}
This will add round red buttons on the left hand corner and you can click on that Delete button will appear click on that and row will be deleted.
You can implement delegate method of UITableView as following.
-(UITableViewCellEditingStyle)tableView: (UITableView *)tableView editingStyleForRowAtIndexPath: (NSIndexPath *)indexPath
{
//Do needed stuff here. Like removing values from stored NSMutableArray or UITableView datasource
}
Hope it helps.
you want to be looking for deleteRowsAtIndexPath, with all your code squeezed between [yourTable beginUpdates] & [yourTable endUpdates];
I have refered "Managing the reordering of rows" in "UITableView Programming Guide".
I have written the same code for my application for rearranging the rows of tableView but not able to rearrange the rows in tableView. The delegates "canMoveRowAtIndex" and "moveRowAtIndex" have not been called though I set tableView in editing mode through "setEditing:animated".I dont want to use core data for implementing this.
Can u provide the detailed code for this?? (I would like rearrange the rows of tableView as we do for icons by long press and then moving them)
Are you sure to add properly the "Edit" button ?
On my code (withoutcoredata), with a navigation controller, I have:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animate
{
[super setEditing:editing animated:animate];
[self.navigationItem setHidesBackButton:editing animated:YES];
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
//...
}
If the methods aren't being called, chances are you either haven't set the table view instance's delegate outlet to point to your controller, or you've spelled the names of the delegate methods incorrectly.
One trick to help avoid misspellings is to go to the header file where the methods are declared (in this case, UITableViewController.h) copy the method declaration(s), and paste them into your source file. Otherwise, I try to use Xcode's completion mechanism to ensure that I don't accidentally misspell things.
yesterday I just asked following question.
How to customize tableView Section View - iPhone
I found some new method.
Even in apple documentation I didn't found this method.
Is it some thing like hidden methods?
Does anybody provides all methods listing?
Including sample code.
Say for example.
UITableView methods
Whenever I insert tableView in my view Controller.
I have to either type or copy from some where.
If I want to include picker I have to find out UIPicker methods,
sameway
Alertview, ActionSheet, Tab Bar Controller all has different methods.
Isn't it possible, like if we include A tableView in our ViewController, Automatically all tableview methods are added to .m file.
(For example, A navigation based application has all tableView methods in rootview controller by default)
Let Me Clarify Again,
"I need proper source where all methods (like rootview controller has almost all table methods) "
So, when ever I want to add any control I just copy the code & add to my Project.
The reason Behind this
"We can target on the work instead of finding proper methods & typing them."
See, Suppose If I add a Table View to my View Controller, I must have the methods like ..didSelectAtRow..,..CellForRow...,etc.
So, after adding tableView - for managing table view I have to go for finding methods & type them in my .m file.
Suppose, I add tableView. All methods should be added to my .m file as given below.
<pre>
pragma mark Table view methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 0;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
}
// Override to support row selection in the table view.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here -- for example, create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherView" bundle:nil];
// [self.navigationController pushViewController:anotherViewController animated:YES];
// [anotherViewController release];
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the item to be re-orderable.
return YES;
}
I provided the answer to the question you mentioned - it definitely is in the Apple documentation (although as you say, not in the sample file). Remember the method name is
tableview:didSelectRowAtIndexPath
if you miss off the "tableview:" bit at the beginning and just search for
didSelectRowAtIndexPath
you won't find it in the documentation so easily.
If you look in the documentation that comes with XCode, you will see, for example, all methods that you can implement for the UITableview Delegate, including the one I posted to your previous answer. Just type "UITableview" into XCode help, and then select "UITableview delegate". It will then display all the methods available for you to call, and you can even just copy and paste them straight into your code.
I don't know if anyone's already done this and made the "template" classes you ask about available, but it should be very easy for you to do this yourself if you want.
Hope that helps
Sure; implementors of classes are free to implement any number of methods as a part of a class's internal implementation.
But that doesn't mean that you should use them.
You can use the Objective-C runtime's API for figuring out all the methods and classes, including those that aren't publicly declared.
But don't bother.
Specifically, if a method is not declared in the provided header files and is not documented in the documentation, don't use it. Using such a method will lead to fragility and maintenance headaches; your app may likely break at the next software update.
On the iPhone, your are expressly directed not to use private interfaces and your app will run the risk of rejection if you do so.
But I don't think that is what you are really asking. You mention:
Say for example. UITableView methods
includes
didSelectRowAtIndexPath
cellForRowAtIndex Path
numberOfSectionsInTableView
titleForHeaderInSection
However, UITableView does not declare any of those methods. Instead, it declares:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
Or, succinctly, tableView:didSelectRowAtIndexPath:, etc...
The methods you describe are in the documentation. They're in UITableViewDelegate and UITableViewDataSource, which are described at the top of the UITableView documentation. You can easily copy and paste the method definitions you need from the documentation. You can also find the protocol definition in the headers easily by using "File>Open Quickly..." and typing in the name of the protocol ("UITableViewDelegate" for instance). They are often written in the headers to make it easy to copy and paste what you need most often.
This is sometimes a small hassle in Cocoa, because Xcode doesn't auto-complete method signatures. It would save a little trouble if it did. But the solution is not to implement every delegate method that exists (as #bbum pointed out earlier). In the vast majority of cases, only a small fraction of the possible delegate methods are ever implemented. So automatically populating them all would cause much more work than it saved.