prepareForSegue not passing appropriate row in tableView - objective-c

I have a Table View with Lessons and want to pass lesson's name in detail view controller. But it always passes the first row.
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewRowAction *edit = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"edit" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
[self performSegueWithIdentifier:#"editLesson" sender:nil];
}];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"editLesson"]) {
NSManagedObject *selectedLesson = [self.lessons objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
EditLessonViewController *destViewController = segue.destinationViewController;
destViewController.lesson = selectedLesson;
}
}

You should pass indexPath as sender in performSegue.
There is yours code:
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewRowAction *edit = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:#"edit" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
[self performSegueWithIdentifier:#"editLesson" sender:indexPath];
}];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"editLesson"]) {
NSIndexPath* indexPath = (NSIndexPath*)sender;
NSManagedObject *selectedLesson = [self.lessons objectAtIndex:indexPath.row];
EditLessonViewController *destViewController = segue.destinationViewController;
destViewController.lesson = selectedLesson;
}
}

Related

prepareForSegue after didSelectRowAtIndexPath?

Can we make a rank like prepareForSegue after didSelectRowAtIndexPath?
My NSLog sends a good sentence, this NSLog is that I want (in didSelectRowAtIndexPath but assign AFTER to my NSLog in prepareForSegue) I would like the NSLog in prepareForSegue sends the same sentence that didSelectRowAtIndexPath.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
self.cellSelected = cell.textLabel.text;
NSLog(#"la : %#", self.cellSelected);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showPhotoView"]) {
NSLog(#"ou %#", self.cellSelected);
PhotoViewController *viewController = (PhotoViewController *)segue.destinationViewController;
viewController.cellSelected = self.cellSelected;
}
}
If you use a segue that originates from a UITableViewCell the sender parameter will actually contain the UITableViewCell that was selected. So you could just use the sender parameter to get the data you need.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showPhotoView"]) {
UITableViewCell *cell = sender;
PhotoViewController *viewController = (PhotoViewController *)segue.destinationViewController;
viewController.cellSelected = cell;
}
}
Yes you can ! You need just to fix some things
Here is an example i used
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"friends2" sender:self];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"friends2"]) {
NSString * object = nil;
NSIndexPath *indexPath2 = nil;
if (self.searchDisplayController.isActive) {
indexPath2 = [[ self.searchDisplayController searchResultsTableView]indexPathForSelectedRow];
object = self.results[indexPath2.row];
NSLog(#"is active : %#", object.self);
} else
{
indexPath2 = [self.tableView indexPathForSelectedRow];
object = sortedArray.self[indexPath2.row];
NSLog(#"is not active : %#", object.self);
}
with didSelect.. i just made the segue, and with performSegue you do what you want to do

indexPath.row returns properly with didSelectRow, but not with accessoryButtonTapped?

Here is my code:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"editInfo" sender:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"editInfo"]) {
EditInfoViewController *vc = [segue destinationViewController];
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
NSLog(#"%d",selectedIndex);
[vc setSelectedIndex:selectedIndex];
}
else if ([[segue identifier] isEqualToString:#"sendMessage"]) {
...
}
}
The selectedIndex variable is always NSLogged as 0... Any suggestions? Thanks.
Tapping a UITableViewCell's accessoryButton doesn't select the row containing the accessoryButton.
When you call performSegueWithIdentifier, you could pass indexPath as the sender, which you could then reference in prepareForSegue.

How do I check what tableview is the current one in a segue

How do I check what tableview is the current one in a segue?
Since UISearchDisplayController activates its own tableview, I get another array with results.
This is the code I tried, but it doesn't work.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetails"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if (self.tableView == [[self searchDisplayController]searchResultsTableView]) {
}
DetailViewController *detailViewController = [segue destinationViewController];
detailViewController.myObject = [mySearchArray objectAtIndex:indexPath.row];
}
}
According to Apple website, inside the method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {...}
you would check the tableView
if (tableView == self.tableView) {
return ...;
}
// If necessary (if self is the data source for other table views),
// check whether tableView is searchController.searchResultsTableView.
return ...;

Prepareforsegue navigationItem.title one behind

I'm still relative new to object c, so please bear over with me if this is a rookie question. I'm trying to set the title of my navigationcontroller with the corresponding object information. I'm using prepareforsegue for it, but the first time is segue to the new controller, the title is blank. If i try again, it shows up, but if i pressed something else, it shows the title of the things i pressed the time before. I have embedded my code below.
//.h
#import <UIKit/UIKit.h>
#interface STATableViewController : UITableViewController
#property(strong,nonatomic)NSArray *listOfExercises;
#property(weak,nonatomic)NSString *navTitle;
#end
//.m
#import "STATableViewController.h"
#import "ExercisesViewController.h"
#implementation STATableViewController
#synthesize listOfExercises = _listOfExercises, navTitle = _navTitle;
- (void)viewDidLoad
{
[super viewDidLoad];
_listOfExercises = [NSArray arrayWithObjects:#"Raketstart",#"SpeedBåd",#"Træstamme",nil];
self.navigationItem.title = #"Exercises";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_listOfExercises count];
}
- (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];
}
NSString *cellValue = [_listOfExercises objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_navTitle = [_listOfExercises objectAtIndex:indexPath.row];
//NSLog(_navTitle);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"toExercise"])
{
ExercisesViewController *foo = [segue destinationViewController];
foo.navigationItem.title= _navTitle;
}
}
#end
This is happening because prepareForSegue:sender: is being called before tableView didSelectRowAtIndexPath:. So you are always setting your navigationItem's title before you are setting your _navTitle property with the value you want.
Instead of getting the title in didSelectRowAtIndex path, do it in your prepareForSegue like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"toExercise"])
{
// "sender" is the table cell that was selected
UITableViewCell *cell = (UITableViewCell*)sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSString *title= [_listOfExercises objectAtIndex:indexPath.row];
ExercisesViewController *foo = [segue destinationViewController];
foo.navigationItem.title = title;
}
}

How to seque a subclass of UITableViewCell?

I've created a subclass of UITableViewCell. Until now, I've only been using cells which is "designed" in my storyboard where I can setup segues.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[super prepareForSegue:segue sender:sender];
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
if ([[segue identifier] isEqualToString:#"showNews"]) {
NewsViewController *newsViewController = [segue destinationViewController];
News *news = (News*)[self.fetchedResultsController objectAtIndexPath:indexPath];
newsViewController.news = news;
}
}
After I've created my subclass of UITableViewCell I'm no longer able to use the Storyboard to create segues for the custom cell, right? I've tried to create a cell in the storyboard and set its class to my custom class -- but then the cell is just blank when I run the App.
So instead I'm just alloc and init the custom cell in my tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"WSTableViewCell";
WSTableViewCell *cell = (WSTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[WSTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
WSObject *item = [self.fetchedResultsController objectAtIndexPath:indexPath];
[cell.titleLabel setText:item.title];
return cell;
}
Then in tableView:didSelectRowAtIndexPath I'm trying to creating the NewsViewController, setting the news item and push it to the navigationController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
News* news = [self.fetchedResultsController objectAtIndexPath:indexPath];
NewsViewController *newsViewController = [[NewsViewController alloc] init];
newsViewController.news = news;
[[self navigationController] pushViewController:newsViewController animated:YES];
}
But when I select a row my NewsViewController is not shown -- but instead I see a blank view with a black background. How can I deal with this? Is it possible to still use seques?
The problem I think is that you are using alloc-init to instantiate NewsViewController. That does not create your NewsViewController from storyboard. You have to use [UIStoryboard instantiateViewControllerWithIdentifier:(NSString *)identifier] to instantiate from storyboard.
However, I think the easier way is to call
[self performSegueWithIdentifier:#"showNews" sender:indexPath]
in your didSelectRowAtIndexPath. You have to change your prepareForSegue... a little bit.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = (NSIndexPath *)sender;
if ([[segue identifier] isEqualToString:#"showNews"]) {
NewsViewController *newsViewController = [segue destinationViewController];
News *news = (News*)[self.fetchedResultsController objectAtIndexPath:indexPath];
newsViewController.news = news;
}
}