TableView delete after I click button delete - iphone

So I am trying to delete rows in table view.
Here is my code:
- (IBAction)done:(UIStoryboardSegue *)segue
{
DetailGodsViewController *detailController = [segue sourceViewController];
NSIndexPath *path = [NSIndexPath indexPathForRow:detailController.row inSection:detailController.section];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path]
withRowAnimation:NO];
[self.listOfGoods deleteGood: detailController.row];
[[self tableView] reloadData];
[self dismissViewControllerAnimated:YES completion:NULL];
}
I have ControlViewTable in storyBoard, after I click on a row in ControlViewTable it jumps to Detail view And there is other info, also I store info about the row and section in this function:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowGoodDetails"]) {
DetailGodsViewController *detailViewController = [segue destinationViewController];
detailViewController.row = [self.tableView indexPathForSelectedRow].row;
detailViewController.section = [self.tableView indexPathForSelectedRow].section;
detailViewController.good = [self.listOfGoods getGoodAtIndex:detailViewController.row ];
}
and there is also a button in detail view for delete, after I click on it, it jumps to the function:
- (IBAction)done:(UIStoryboardSegue *)segue.
But it always crashes in deleteRows. Could someone please help?

One problem might be that you're still responding to the button while you're trying to get rid of the cell containing the button. You need to let that action method end, and then call deleteRows. You should probably do the sort of thing I recommend here:
https://stackoverflow.com/a/13907375/341994
However, the biggest problem is probably that you must update the model data before deleting a row of the table.

Your code in the done: method is doing a few things out of order plus some extra things you don't need. It should be:
- (IBAction)done:(UIStoryboardSegue *)segue
{
DetailGodsViewController *detailController = [segue sourceViewController];
NSIndexPath *path = [NSIndexPath indexPathForRow:detailController.row inSection:detailController.section];
[self.listOfGoods deleteGood: detailController.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:path]
withRowAnimation:NO];
[self dismissViewControllerAnimated:YES completion:NULL];
}
Basically, you need to update your data before you update the table. Also, don't call reloadData on the table after calling deleteRowsAtIndexPaths:. Do one or the other, not both.

Related

xcode ios: prepareForSegue - same data 2 display. 2nd display data error

I'm in the process of learning to use the storyboard to create tables.
When user Tabs on the cell, it goes to View A, while if user Tabs on the arrow icon on the right inside the cell it goes to View B.
Both A & B are to display the same data, just the layout is different. I'm using UIViewController for A and UITableViewController for B. Its just having different layout but same data.
The problem I have is that, view A shows the correct data for each cell, but view B always shows the data of cell[0] no matter which cell I Tab on.
The prepareForSegue code is as follow:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
`if ([[segue identifier] isEqualToString:#"ShowCarDetails"])
{
CarDetailViewController *detailViewController =
[segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView
indexPathForSelectedRow];
int row = [myIndexPath row];
detailViewController.carDetailModel = #[_carMakes[row],
_carModels[row], _carImages[row]];
}
else if ([[segue identifier] isEqualToString:#"niceDetails"])
{
StaticTableViewController *detailViewController =
[segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView
indexPathForSelectedRow];
int row = [myIndexPath row];
detailViewController.carDetailModel = #[_carMakes[row],
_carModels[row], _carImages[row]];
}
}
Can someone point out where's the error here?? Thanks!
And otherwise check the data in the StaticTableViewController.
Are you synchronising the data etc?

Segue Headaches in Xcode

I have a tableview and I created a segue to push it to another view controller. Every now an then this segue breaks without me touching it I can guarantee. I didn't even edit the file I put it in.
My Code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *acell = [tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"cellWasSelected" sender:acell];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"cellWasSelected"])
{
if ([sender isKindOfClass:[UITableViewCell class]])
{
UITableViewCell *selectedCell = sender;
ViewController *myDetViewCont = segue.destinationViewController;
myDetViewCont.navigationItem.title = selectedCell.textLabel.text;
}
}
}
First after clicking a cell xcode directs me to the file this segue pushes to.
It redirects me here: action:#selector(handleSingleTap:)];
I use this for my images to trigger this: [self.navigationController popToRootViewControllerAnimated:YES]
If I choose in Thread 1 my main view I see the problem is:
[self performSegueWithIdentifier:#"cellWasSelected" sender:acell];
But whats the problem I used this athousand times and it starts crashing without me changing it.
Your code don't have any bugs, the problem is somewhere else. May be you have not give the segue an identifier in interface builder. Try this code. It is working on my side, if your files don't have any problem it should run on your side too.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSString* identifier = [segue identifier];
if ([identifier isEqualToString:#"cellWasSelected"]) {
NSLog(#"Performing Seque");
if ([sender isKindOfClass:[UITableViewCell class]]) {
NSLog(#"correct");
UITableViewCell *selectedCell = sender;
UIViewController* myDetViewCont = segue.destinationViewController;
myDetViewCont.navigationItem.title = selectedCell.textLabel.text;
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",#"Cell Selected");
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"cellWasSelected" sender:cell];
}
P.S. If you are still having problems you, then may be you are new to storyboard and you need enough knowledge to work on them.
http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1

Scroll a table view to a cell, then flash the cell

I have a table view with a number of cells. When I add a new cell (using a modal view controller) I'd like to show the user the newly added cell. To do this I want to scroll the table view to the new cell, select it and immediately deselect it.
Right now, I'm sending a deselectRowAtIndexPath to my table view after a timed interval:
- (IBAction)selectRow
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:7 inSection:0];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
[self performSelector:#selector(deselectRow:) withObject:indexPath afterDelay:1.0f];
}
- (void)deselectRow:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
I'm wondering if there's a nicer way to do this. It works well, but I don't like relying on a static timer to perform an operation which could sometimes take a different amount of time (e.g. if the table was very long).
Edit: Note that selectRowAtIndexPath:animated:scrollPosition won't cause the UITableView delegate methods to get fired. Neither tableView:didSelectRowAtIndexPath: nor scrollViewDidEndDecelerating: will be called. From the docs:
Calling this method does not cause the delegate to receive a tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath: message, nor will it send UITableViewSelectionDidChangeNotification notifications to observers.
UITableViewDelegate is an extension of UIScrollViewDelegate. You could implement one of the UIScrollViewDelegate methods and use that to determine when to deselect the row. scrollViewDidEndDecelerating: seems like a good place to start.
Also, I personally find the performSelector... methods limiting due to the 1 parameter restrictions. I prefer to use GCD. The code would look like this:
- (IBAction)selectRow
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:7 inSection:0];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
//deselect the row after a delay
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
});
}

Programmatically highlight first row in tableview after first load

Im trying to highlight the first row in my table upon first loading the data and just cannot get it to work!
I have tried lots of ways with no joy, the latest attempt being this:
NSUInteger indexArr[] = {0,1};
NSIndexPath *n = [NSIndexPath indexPathWithIndexes:indexArr length:2];
[self.tableView scrollToRowAtIndexPath:n atScrollPosition:UITableViewScrollPositionTop animated:NO];
try
[self.tableView selectRowAtIndexPath:n animated:YES scrollPosition:UITableViewScrollPositionTop];
you should probably do this after your view has appeared.

UITable cell selection in a SplitViewController

I have a UISplitViewController with a Table View for navigation. It's similar to the Mail app. When you click on a table view in portrait mode, the popup hides itself. When you click on the nav bar to get the popup back, the selected item no longer appears selected. How can make this item appear selected without re-selecting the item? (just like in the mail app)
In your viewDidLoad method, do you call
self.clearsSelectionOnViewWillAppear = NO; ?
This is how Xcode's SplitView template does it.
Do you have by any change a
[tableView deselectRowAtIndexPath:indexPath animated:YES];
in your didSelectRowAtIndexPath in the RootViewController ?
I've got a solution that works, but it's frustratingly hacky. I have to call selectRowAtIndexPath twice. It seems that cellForRowAtIndexPath is invalidating the selection made in viewWillAppear. It still needs to be called in viewDidAppear, however, so the view scrolls to the proper position before cellForRowAtIndexPath is called.
- (void)viewWillDisappear:(BOOL)animated
{
NSIndexPath *selected = [self.tableView indexPathForSelectedRow];
_selectedRow = selected.row;
}
- (void)viewDidAppear:(BOOL)animated
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_selectedRow inSection:0];
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//initialize cell code here...
if (indexPath.row == _selectedRow) {
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
}
For your table view controller, is -viewWillAppear: called before the pop-up is displayed? If so, you could write it as so:
- (void)viewWillAppear:(BOOL)animated
{
[self.tableView selectRowAtIndexPath:<indexPath>
animated:animated
scrollPosition:UITableViewScrollPositionMiddle];
[super viewWillAppear:animated];
}
Obviously, replace <indexPath> with the proper index path and set the scroll position how you want it. You may also want to pass NO instead of animated to make it appear like it was selectd before the view appeared.