didSelectRowAtIndexPath and prepareForSegue implementation - ios

I have two methods :
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
testNumber=indexPath.row;
testNumber=testNumber+1;
NSLog(#"Test number : %i",testNumber);
}
then
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"testStart1"])
{
tViewController *tvc = [segue destinationViewController];
tvc.testNumberTVC=testNumber;
}
}
I have got also a segue who is triggered by selecting a row in my UITableView.
My problem is when I select a row, prepareForSegue is acting before didSelectRowAtIndexPath so the new value of testNumber is not transferred.
I would like to implement prepareForSegue only when didSelectRowAtIndexPath is done or better:
Transfer the value of testNumber using only didSelectRowAtIndexPath method and so removing prepareForSegue method.
I've seen few topics about transfering data from UITableView to DetailView but with the new xCode 5, when an error message appears, I don't really know if this is because solution is outdated or if there is a real error is my code.

You could create your segues between the view controllers rather than from cell selection and set the identifier of the segue in the storyboard. Then you could do something like this:
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
testNumber=indexPath.row;
testNumber=testNumber+1;
NSLog(#"Test number : %i",testNumber);
[self performSegueWithIdentifier:#"mySegueIdentifier" sender:self];
}
Another option would be to check out the answer to this link here. Basically you can get the cell indexPath in prepareForSegue like this:
UITableViewCell *cell = (UITableViewCell*)sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

Related

How to pass value from a selected cell in embedded collectionView to another viewController?

In UIViewController 1, I have set up an array. This UIViewController segues to UIViewController 2.
In UIViewController 2, there is a UITableView with custom UITableViewCell. There's also a UIButton which segues perfectly fine back to UIViewController 1.
In the custom cell, there is a collectionView. This is populated by the array from ViewController 1.
My question is, when an item is selected in the collectionView (UIViewController 2 - custom UITableViewCell class), how to pass that value all the way back to UIViewController 1?
I'm sorry if this is repetitive. I've referred to many similar entries here but nothing seems to be working. I've also tried this:
http://www.appcoda.com/ios-collection-view-tutorial/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipePhoto"]) {
NSArray *indexPaths = [self.collectionView indexPathsForSelectedItems];
RecipeViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = [indexPaths objectAtIndex:0];
destViewController.recipeImageName = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
[self.collectionView deselectItemAtIndexPath:indexPath animated:NO];
}
}
I keep getting the null value returned and I'm not sure why.
(I'm not using storyboard. And this is my first attempt at programming of any kind. Would appreciate any input!)
You can use UICollectionViewDelegate.
Add in your class:
class YourViewController: UIViewController, UICollectionViewDelegate { ... }
and use - (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath this event is called when the cell is selected; you must save the value in a property; like that:
- (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
selectedRecipeImageName = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
...
[self.collectionView deselectItemAtIndexPath:indexPath animated:NO];
}
and then:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipePhoto"]) {
RecipeViewController *destViewController = segue.destinationViewController;
destViewController.recipeImageName = selectedRecipeImageName
}
}
You can do it either with delegation or completion block.
To solve with delegation please follow this link.
To solve with completion block please follow this link.

indexPath has no value in Table View

I have a table view displaying a list of contacts and when you click a cell, a detail view controller pops up with labels showing the contact name, number, fax, and address. My problem is that every time I click a cell, the first value in the plist pops up no matter which cell i click. I found my error in indexPath when NSLog(#"%#",indexPath); returned null everytime. I think the problem is in this method but it looks the same in other classes and works fine.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showCountyInfo"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"%#",indexPath);
TSPBookCoverViewController *destViewController = segue.destinationViewController;
destViewController.countyName = [[self.books objectAtIndex:indexPath.row] objectForKey:#"Name"];//error
destViewController.phoneName = [[self.books objectAtIndex:indexPath.row] objectForKey:#"Phone"];
destViewController.faxName = [[self.books objectAtIndex:indexPath.row] objectForKey:#"Fax"];
destViewController.addressName = [[self.books objectAtIndex:indexPath.row] objectForKey:#"Address"];
}
}
When I enter integers instead of indexPath.row, it works like it should, so the problem is here I just can't find it. Sorry if it's obvious I've tried looking for awhile now!
Edit:
Here is didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Perform Segue
[self performSegueWithIdentifier:#"showCountyInfo" sender:self];
}
The issue is with the following code:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
You are deselecting the cell inside the didSelectRowAtIndexPath: method. So the indexPathForSelectedRow will always return nil
Best way for you to resolve it is to get the Dictionary from self.books array in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
and then perform the segue and get values from that dictionary in prepareForSegue

Is using tableView:willSelectedRowAtIndexPath: correct way to pass variable?

Hello i am trying to pass variable with segue.
I am getting variable to pass with tableView:willSelectedRowAtIndexPath: is this correct way? If it is not, how should i achieve this? (Note: It is working like this.)
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
selectedCoffeeShop = [coffeeShops objectAtIndex:indexPath.row];
return indexPath;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"coffeeShopDetailSegue"]) {
CoffeeShopDetailViewController *controller = (CoffeeShopDetailViewController *)segue.destinationViewController;
[segue destinationViewController];
controller.coffeeShop = selectedCoffeeShop;
}
}
If your segue is made from the cell itself, then there is no need to implement either willSelectRowAtIndexPath or didSelectRowAtIndexPath. You only need prepareForSegue:sender: since the sender argument will be the cell, and you can use that to get the indexPath you need,
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(UITableViewCell *)sender {
if ([segue.identifier isEqualToString:#"coffeeShopDetailSegue"]) {
NSInteger row = [self.tableView indexPathForCell:sender].row;
CoffeeShopDetailViewController *controller = segue.destinationViewController;
controller.coffeeShop = coffeeShops[row];
}
}
That way to do it is absolutely fine.
Another way would be to remove the automatic segue trigger from storyboards and instead implement:
tableView:didSelectRowAtIndexPath: to call performSegueWithIdentifier:sender:.
It could look like this:
- (NSIndexPath *)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedCoffeeShop = [coffeeShops objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"coffeeShopDetailSegue" sender:self];
return indexPath;
}
In that case you still need your implementation of prepareForSegue:sender:.
You could also do it completely without segues, using UINavigationController, but then you'd have to instantiate the CoffeeShopDetailViewController programmatically as well.
Your approach is perfectly fine though!
As noted in the comments, you can remove [segue destinationViewController];, since this returns the destination view controller which you already saved in the variable controller in the line right above. :)

How to obtain data passed in performSegueWithIdentifier

This will probably take two seconds to answer, but my search skills have not gotten me very far on this issue. I am performing a segue but I'm not sure how to grab the id on the destination. Here is my code on the tableview controller.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath: NSIndexPath *)indexPath{
NSLog(#"reaching accessoryButtonTappedForRowWithIndexPath:");
[self performSegueWithIdentifier:#"leads_calls_to_detail" sender:[[self.leads_calls objectAtIndex:indexPath.row] objectForKey:#"ID"]];
}
What do I have to create on my destination view controller to be able to grab the id that I'm attempting to pass, or is the way I'm performing my segue incompatible with what I am attempting?
You should just pass values to the destinationViewController inside prepareForSegue: and pass self as the sender.. try using something like:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"leads_calls_to_detail"])
{
YourViewController *controller=(YourViewController *)segue.destinationViewController;
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
//Or rather just save the indexPath in a property in your currentViewController when you get the accessoryButtonTappedForRowAtIndexPath callback, and use it here
controller.yourPropertyToSet = [self.leads_calls objectAtIndex:path.row];
}
}
And also according to Rob Mayoff, you can grab the index path for the row that the accessory was tapped at by using something like this:
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];//where sender is the sender passed in from prepareForSegue:
How to find indexPath for tapped accessory button in tableView

custom cell didSelectRowAtIndexPath not called

I created a universal master-detail application. I have a table view within a custom class (MasterViewController class). This is a UITableViewController class.
Using Storyboard, I created a custom cell in my iPhone table view. The custom cell contains 3 labels and 1 image.
In StoryBoard, this table view datasource and delegate is set to the MasterViewController class.
My custom table view cell has 'User Interaction Enabled' in the View section of the attribute inspector.
In my MasterViewController class, the UITableViewDataSource methods such as 'numberOfSectionsInTableView' are working fine.
I have a seque defined between the table view and a detailed view.
When I run the application and select a cell in the table view, the didSelectRowAtIndexPath is not called for the iPhone. My prepareForSegue method executes and the segue occurs.
I have read quite a number of posts on didSelectRowAtIndexPath not being executed, but I have not been able to solve my problem.
Any hints would be very much appreciated.
My custom cell identifier is ConversationCell. The segue identifier is ShowConversationDetails.
I debug with a breakpoint on the first line of numberOfRowsInSection and this method is never entered.
The segue works and the detail view displays my label with 'Hello' text.
Some Code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
//NSLog(#"Rows %lu",(unsigned long)[sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ConversationCell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[[self.fetchedResultsController sections] count]);
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
self.detailViewController.detailItem = object;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowConversationDetails"]) {
NSIndexPath *selectedIndex = [self.tableView indexPathForSelectedRow];
Event *e = nil;
e = [self.fetchedResultsController objectAtIndexPath:selectedIndex];
UIViewController *destinationViewController = [segue destinationViewController];
[segue.destinationViewController setLabel:#"Hello"];
}
}
MASTERVIEWCONTROLLER:
Here is my interface for above;
#interface MasterViewController : UITableViewController <NSFetchedResultsControllerDelegate,ASIHTTPRequestDelegate,UITableViewDelegate, UITableViewDataSource>
{
NSMutableArray *eventsArray;
}
This may be a clue to my problem. When I add the following code to prepareForSeque
NSIndexPath *selectedIndex = [self.tableView indexPathForSelectedRow];
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:selectedIndex];
NSString *messageTableID = [[object valueForKey:#"messagetableid"] description];
selectedIndex is empty as if a row is no longer selected when prepareForSeque is executing.
By the way, just to be safe, I removed the app from the simulator and then did a Clean on the project and nothing changed.
Tim
In addition to the checks you have already mentioned, here are a few other ones you might want to consider:
Check that the method is exactly this (no difference in letter cases) :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Check that the controller implements the UITableViewDelegate protocol
Check that interaction does work (change the selection style option so that the cell changes color on touch events)
Check that you don't have any view inside that is first responder and takes away the interaction (remove any view in the cell to test)
Try to programmatically allow selection on the table [tableView setAllowsSelection:YES];
Are you sure that your UITableViewDelegate object is correctly being set as the table view's delegate? (This is separate from setting it as the data source.)
I ended up deleting my MasterViewController and DetailViewController. I recreated them and things are now working. Not sure what I did wrong the first time. Thanks for everyone that offered advice.
Tim

Resources