iOS override a Segue - ios

I have a tableview controller and I would like to override the segue for the final row. Instead of going to the standard destination view controller I want to send it to another controller. How do I do this?
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *myIndexPath = [self.tableView
indexPathForSelectedRow];
long row = [myIndexPath row];
if ([[segue identifier] isEqualToString:#"ShowLocationsTableView"])
{
LocationsTableViewController *ViewController =
[segue destinationViewController];
ViewController.categoryDetailModel = #[_categoryTitle[row],
_categoryImages[row]];
}
}
This is the current prepareForSegue and I would like to change it. I would like to send it to another view controller using a segue "aboutCat". How do I do this?
I don't understand what happens between prepareForSegue [current] and viewDidLoad [destination]. Thanks
Sideeffects
Initial problem was solved by 'Nikita Took' yet there are some side effects
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
long row = [myIndexPath row];
if ([_categoryTitle[row] isEqualToString:#"About"])
{
NSLog(#"SKIPPING PREPARE");
}
else if ([[segue identifier] isEqualToString:#"ShowLocationsTableView"])
{
LocationsTableViewController *ViewController =
[segue destinationViewController];
ViewController.categoryDetailModel = #[_categoryTitle[row],
_categoryImages[row]];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.tableView)
{
// I assume you have 1 section
NSLog(#"DIDSELECTROW");
NSLog(#"INDEX PATH %i", indexPath.row + 1);
NSLog(#"%i", [tableView numberOfRowsInSection:0]);
if (indexPath.row + 1 == [tableView numberOfRowsInSection:0])
{
NSLog(#"ABOUT");
[self performSegueWithIdentifier:#"aboutCat" sender:self];
}
else
{
NSLog(#"ELSE");
[self performSegueWithIdentifier:#"ShowLocationsTableView" sender:self];
}
}
}
Now the about works!!! But if I click on another row which is one of the mainSegue. It will call the subview controller 2x. I can verify this with NSLOG statements in the detailview viewdidload. The issue is that now the navigation controller takes two steps to return home.
[home] -> [detail view] -> [same detail view]
I can verify that the didselectrowatindexpath happens before the prepareforsegue
Any ideas why two segues are preformed?

Assume you have two segues: MainSegue (for all rows except the last one) and LastRowSegue (for the last row) you can do:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.tableView) {
// I assume you have 1 section
if (indexPath.row == [tableView numberOfRowsInSection:0]) {
[self performSegueWithIdentifier:#"LastRowSegue" sender:self];
} else {
[self performSegueWithIdentifier:#"MainSegue" sender:indexPath];
}
}
}
Try this for prepareForSegue. If it's not what you need, please explain what do you mean
It works but I'm getting double layered table views
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"MainSegue"]) {
NSIndexPath *selectedIndexPath = sender;
LocationsTableViewController *locationController = segue.destinationViewController;
locationController..=categoryDetailModel = #[_categoryTitle[selectedIndexPath.row], _categoryImages[selectedIndexPath.row]];
}
}

You can't do this in prepareForSegue -- the source and destination view controllers are already defined by the time prepareForSegue is called. You need to make two segues from your controller (not the cell) and call performSegueWithIdentifier:sender" in didSelectRowAtIndexPath. Choose which segue to perform based on the indexPath.

You can do something like this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int lastIndex=[tableArray count]-1;
if (indexPath.row == lastIndex) {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
NSString* viewType = #"MenuVC";//u can have the identifier of the LocationViewCOntroller or where ever you wanna go from here
UIViewController* viewController = [storyboard instantiateViewControllerWithIdentifier:viewType];
self.navigationController.viewControllers = [NSArray arrayWithObjects:viewController, nil];
} else {
[self performSegueWithIdentifier:#"usualSegue" sender:self];
}
}

Related

Issue to choose a cell in a section of a TableView

I have a UITableViewController with three sections and a variable number of cells for each one and when I tap on a cell, I have a detail view.
I use a segue to send the information to my other view. But I saw that if I the for example the first cell of the second section I will have the first cell of my first section. I tried to fix that by indicating the section and the cell but my program doesn't recognize indexPath.section.
Here is my code of the segue :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue isKindOfClass:[TLAnimatedSegue class]]) {
((TLAnimatedSegue *) segue).delegate = self;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
TVDetailsViewController *destViewController = segue.destinationViewController;
destViewController.details = [[_scheduleList objectAtIndex:indexPath.section]objectAtIndex:indexPath.row];
}
}
I don't understand why I have en error with that because when I po my indexPath, I have two element inside. With the breakpoint, this line seems to be the reason of the crash :
destViewController.details = [[_scheduleList objectAtIndex:indexPath.section]objectAtIndex:indexPath.row];
Thanks for your help.
Thank you #zcui93 and #Rohit KP, you open my mind and eyes so here is the solution to tackle this little issue and now it works :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue isKindOfClass:[TLAnimatedSegue class]]) {
((TLAnimatedSegue *) segue).delegate = self;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
TVDetailsViewController *destViewController = segue.destinationViewController;
if(indexPath.section == 0) {
destViewController.details = [_pastScheduleList objectAtIndex:indexPath.row];
}
if(indexPath.section == 1) {
destViewController.details = [_currentScheduleList objectAtIndex:indexPath.row];
}
if(indexPath.section == 2) {
destViewController.details = [_futurScheduleList objectAtIndex:indexPath.row];
}
}
}
Use didSelectRowAtIndexPath method and get cell content using as describe below and perform segue
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
....
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
String id = cell.textLabel.text;
/*... perform segue operation... */
....
}
/* ... for( Customcell *cell = (CustomCell*)... ) ...

Getting same records from UITableView on Detail Button click in iOS

I am newbie to iOS and learning things in iOS. I am making a demo of UITableView and Segue. I have successfully implemented table-view and now I want to pass the value to another View Controller using segue. I have tried as below, but my problem is I am getting same record every time on detail button clicked from UITableView. I don't have any idea what is wrong in my code.
Can anybody help me to figure it out?
I am posting my code here:
code
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
//NSDictionary *dict = [myArray objectAtIndex:indexPath.row];
// NSString *name = [dict valueForKey:#"name"];
[self performSegueWithIdentifier:#"detail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"detail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
//NSLog(#"selected index path==%#",indexPath);
DetailView *destViewController = segue.destinationViewController;
destViewController.details = [myArray objectAtIndex:indexPath.row];
}
}
Change your code as below, you don't need to send self as the sender. Send indexPath
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"detail" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"detail"]) {
NSIndexPath *indexPath = sender;
DetailView *destViewController = segue.destinationViewController;
destViewController.details = [myArray objectAtIndex:indexPath.row];
}
}

How to use SWRevealVC with didSelectRowAtIndexPath and prepareForSegue?

I have a problem with using SWRevealViewController. How to call prepare for segue in didSelectRowAtIndexPath? It is necessary because in tableView I have name of categories and some of this categories have its own subcategories. For example my list:
- category1
- category2
+ category3
- category4
So, when I click on + category3 I should see
- category1
- category2
+ category3
- subcategory1
- subcategory2
- category4
But I could not to do this because of prepareForSegue
Here is my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section <= _categories.count) {
GDCategory *category = [[_subCategories objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
_gdCategory = category;
if (category.subcategories.count > 0) {
NSNumber *categoryId = #(category.dbId);
if ([_selectedSubCategories containsObject:categoryId]) {
[_selectedSubCategories removeObject:categoryId];
} else {
[_selectedSubCategories addObject:categoryId];
}
NSLog(#"There are %lu subcategories in %#", (unsigned long)category.subcategories.count, category.name);
[self recalcSubcategories];
[tableView reloadData];
} else {
//Here I should call prepareForSegue
}
NSLog(#"selected category is %#", category.name);
}
}
- (void)prepareForSegue: (UIStoryboardSegue *)segue sender:(id)sender {
// configure the destination view controller:
if ( [sender isKindOfClass:[UITableViewCell class]] ) {
UINavigationController *navController = segue.destinationViewController;
GDCategoryVC *categoryVC = [navController childViewControllers].firstObject;
if ( [categoryVC isKindOfClass:[GDCategoryVC class]] ) {
categoryVC.selectedCategory = _gdCategory;
}
}
}
Also, I could not to pass data throw VCs, because prepareForSegue call firstly. Please help me. Thanks!
//in prepareForSegue method
NSIndexPath *indexPath = [tableView indexPathForSelectedRow];
and you can get selected row value by using indexPath.row
To change the current View you shouldn't call prepareForSegue. Use performSegueWithIdentifier instead. PrepareForSegue will be called automatically.
If you want to pass the UITableViewCell as sender you need to call the cellForRowAtIndexPath from your TableViewDataSource
else {
//Here I should call prepareForSegue
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath] //call self if dataSource is implement in your class
[self performSegueWithIdentifier:segueIdentifier sender:cell] // Insert your identifier for the wished Segue
}
With SWRevealController it can happen that the View did changed like it should, but the RevealMenu is still visible. For that issue you can call:
[self.revealViewController setFrontViewPosition:FrontViewPositionLeft animated:YES];

Segue not passing correct indexpath of row always section 0

I'm used sectioned tableView.If I click tableview always it passing indexpath 0 to detail view controller.If I click second row but it indexpath pass always pass 0.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([segue.identifier isEqualToString:#"toNext"]) {
detailTableViewController *detailVC = [segue destinationViewController];
[detailVC setkMessageDict:(NSDictionary*)[nArray objectAtIndex:[self.mytableView indexPathForSelectedRow].section]];
}
What's wrong in code?
You need to create index-path object in to your seque like:-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"toNext" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
NSIndexPath *indexPath = [self.tableview indexPathForSelectedRow];
NSLog(#" indexPath row %d",indexPath.row);
NSLog(#" indexPath row %d",indexPath.section);
detailTableViewController *detailVC = [segue destinationViewController];
[detailVC setJobDetailDict:(NSDictionary*)[nArray objectAtIndex:indexPath.row];
}
Yes Ramdy, is right You need to mention row instead of section.
You use this....
[detailVC setJobDetailDict:(NSDictionary*)[nArray objectAtIndex:[self.mytableView indexPathForSelectedRow].row]];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([segue.identifier isEqualToString:#"toNext"]) {
NSIndexPath *selectedIndex= [self.mytableView indexPathForSelectedRow];
NSDictionary *myDic=(NSDictionary*)[nArray objectAtIndex:indexpath.section];
detailTableViewController *detailVC = [segue destinationViewController];
[detailVC setkMessageDict:(NSDictionary*)[[myDic objectForKey:#"locations"] objectAtIndex:selectedIndex.row]];
}
Please check your Array having the proper data from your section tableview otherwise add the NSDictionary value to array and pass it to detailTableViewController then try.Problem is your are not passing indexpath of section here.Hope its helpful for you.
Try updating the selected row indexPath using API:
selectRowAtIndexPath:animated:scrollPosition:
in the following UITableViewDelegate API:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * currentRow = [NSString stringWithFormat:#"%ld",(long)indexPath.row]; // Declare this row variable in .h file
NSString * currentSection = [NSString stringWithFormat:#"%ld",(long)indexPath.section]; // Declare this section variable in .h file
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([segue.identifier isEqualToString:#"toNext"]) {
detailTableViewController *detailVC = [segue destinationViewController];
detailVC.PassRow = currentRow;
detailVC.PassSection = currentSection;
}
The closest answer to the question is Nitin Gohel. But if you have connected the UITableViewCell to the detailTableViewController in the Storyboard, his method is also wrong.
In that case, the prepareForSegue method is provided with the correct UITableViewCell as a parameter stored in the sender parameter. This is entirely handled by UITableView. So the correct code would be:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([sender isKindOfClass:[UITableViewCell class]] && [segue.identifier isEqualToString:#"toNext"])
{
NSIndexPath *indexPath = [self.mytableView indexPathForCell:sender];
detailTableViewController *detailVC = [segue destinationViewController];
[detailVC setJobDetailDict:(NSDictionary*)[nArray objectAtIndex:indexPath.row];
}
}
Do not forget to check for correct segue name.

UITableView Accessory Button Segue Not working

I'm having big problems learning how to pass data from the cell accessory button to the detail view controller with segues. If I tap the cell the data is passed to the detail view controller in a NSString *selectedItem; and the label on the other view updates with the word that was in the cell -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"toDetail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"toDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DrugDetailViewController *destViewController = segue.destinationViewController;
destViewController.selectedItem = [[candyArray objectAtIndex:[indexPath row]] name];
}
}
And i connect a segue on the storyboard from the cell to the detail view with a name "toDeatil" It works when i click the cell it goes to the detail screen, but if i put
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"toDetail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"toDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DrugDetailViewController *destViewController = segue.destinationViewController;
destViewController.selectedItem = [[candyArray objectAtIndex:[indexPath row]] name];
}
}
Almost exactly the same but from the accessorybutton and I connect a segue on the storyboard from the cell accessorybutton to the detail view with a name "toDetail" when I click the cell it goes to the detail screen, but the information is not there, the label dosent get filled out or just uses the first cell detail all the time.
I've tried heaps of combinations. I've tried making my own accessory button, a UIButton in a custom cell but it just uses the first cells details all the time.
The goal is to get didSelectRowAtIndexPath going to one view and accessoryButtonTappedForRowWithIndexPath going to a different view but I need to tell accessoryButtonTappedForRowWithIndexPath what cell was pressed.
Hope this makes sence.
Thank you
You can pass the indexPath as sender to the performSegueWithIdentifier call, like this:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"toDetail" sender:indexPath];//IndexPath as sender
}
And in your prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"toDetail"]) {
//Detect sender class and act accordingly
NSIndexPath *indexPath = [sender isKindOfClass:[NSIndexPath class]] ? (NSIndexPath*)sender : [self.tableView indexPathForSelectedRow];
DrugDetailViewController *destViewController = segue.destinationViewController;
destViewController.selectedItem = [[candyArray objectAtIndex:[indexPath row]] name];
}
}
You don't need to implement accessoryButtonTappedForRowWithIndexPath.
When prepareForSegue is fired from an accessory view, the sender:(id)sender parameter is set to the UITableViewCell which contains the accessory view. You can then ask the table view for the index of that cell (not the selected index).
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"toDetail"] && [sender isKindOfClass:[UITableViewCell class]]) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
DrugDetailViewController *destViewController = segue.destinationViewController;
destViewController.selectedItem = [[candyArray objectAtIndex:[indexPath row]] name];
}
}
That is because [self.tableView indexPathForSelectedRow] will return a NSIndexPath only if the ROW is tapped, not when the accessory button is tapped.
In accessoryButtonTappedForRowWithIndexPath, you will need to pass indexPath.row to the prepareForSegue method manually. Try this:
NSInteger selectedRow;
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
selectedRow = indexPath.row;
[self performSegueWithIdentifier:#"toDetail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"toDetail"])
{
DrugDetailViewController *destViewController = segue.destinationViewController;
destViewController.selectedItem = [[candyArray objectAtIndex:selectedRow] name];
}
}
What about, if you drive state of what is selected on application delegate! Answer of Raul Juarez do the work, but the target of sender parameter is other!
I have an app that use UITableView, and i need to know what item was touched on accessory button in above screen!
To manage this scenery, i have one property on application delegate, that i update when i touch table view accessory button; so in the next screen, i can retrieve the item touched reading the property of application delegate.
In general, i use de application delegate to code model application (dividing necessary class), so views instances only interact with this model to update necessary states! what i do is focus view work independent of model work!
Maybe some like this:
// Property on Application Delegate
#propety (atomic,readwrite) NSIndexPath* indexTapped;
// Method on UITableViewDelegate instance
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
UIMyAppDelegate* model = (UIMyAppDelegate*)[[UIApplication shared] delegate];
model.indexTapped = indexPath;
[self performSegueWithIdentifier:#"toDetail" sender:self];
}
// Method on another View Controller
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIMyAppDelegate* model = (UIMyAppDelegate*)[[UIApplication shared] delegate];
if ([segue.identifier isEqualToString:#"toDetail"]) {
NSIndexPath *indexTapped = model.indexSelected;
DrugDetailViewController *destViewController = segue.destinationViewController;
destViewController.selectedItem = [[candyArray objectAtIndex:[indexPath row]] name];
}
}

Resources