If statement based on whatever the previous view controller was - ios

Here is what I go so far:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (preivousViewController isEqualToString:#"...")
{
if ([self.filteredArray count] == 0)
self.person = self.users[indexPath.row];
else
self.person = self.filteredArray[indexPath.row];
self.mugshot = cell.imageView.image;
[self performSegueWithIdentifier:#"SelectPerson" sender:self];
} else {
if ([self.filteredArray count] == 0)
self.person = self.users[indexPath.row];
else
self.person = self.filteredArray[indexPath.row];
self.mugshot = cell.imageView.image;
[self performSegueWithIdentifier:#"selectVisitee" sender:self];
}
}
It looks messy, that's why im trying to fix it up (that previousViewController part is just made up to show you what I want to try to do).
What im trying to say is: If how you got to this view was via this segue, or from that view controller with the name suchandsuch, then preform this segue or that segue. Is there a way I can do that?

You can check the previous ViewController of the stack from the Navigation Controller.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([self.filteredArray count] == 0)
self.person = self.users[indexPath.row];
else
self.person = self.filteredArray[indexPath.row];
self.mugshot = cell.imageView.image;
//Not the viewcontroller name string. Use the ViewController class name
if ([self backViewController] == YOURVIEWCONTROLLER)
{
[self performSegueWithIdentifier:#"SelectPerson" sender:self];
} else {
[self performSegueWithIdentifier:#"selectVisitee" sender:self];
}
}
Use this below method,
- (UIViewController *)backViewController
{
NSInteger numberOfViewControllers = self.navigationController.viewControllers.count;
if (numberOfViewControllers < 2)
return nil;
else
return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2];
}

Related

iOS Segue opening two view controllers (assuming two table cells clicked)

When I click a table cell in my application it opens two view controllers. Which it seems to assume that I have clicked two cells, since it opens the cell before and the one I have clicked.
The first 3 cells are pretty much static, every other cell underneath the "ingredients" heading are dynamic. Hence why indexPath - 3
I created the segue between the table view and the view controller in the interface builder.
Table View:
First view controller/segue:
Second view controller segue:
Code for the segue:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedIngredient = self.selectedProduct.ingredientsArray[indexPath.row - 3];
[self performSegueWithIdentifier:#"ingViewSegue" sender:self];
NSLog(#"selected ingredient %#", self.selectedIngredient);
}
#pragma mark segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
IngredientWebViewController *webView = segue.destinationViewController;
webView.selectedIngredient = self.selectedIngredient;
}
Number of rows in table:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_selectedProduct.ingredientsArray count] + 3;
}
Code to populate table:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 0)
{
TitleCell* titleCell = (TitleCell*)[self.tableView dequeueReusableCellWithIdentifier:#"TitleCell" forIndexPath:indexPath];
titleCell.nameLabel.text = self.selectedProduct.productName;
titleCell.brandLabel.text = self.selectedProduct.productBrand;
return titleCell;
}
else if(indexPath.row == 1)
{
return [self.tableView dequeueReusableCellWithIdentifier:#"RatingCell" forIndexPath:indexPath];
}
else if(indexPath.row == 2)
{
return [self.tableView dequeueReusableCellWithIdentifier:#"IngredientHeaderCell" forIndexPath:indexPath];
}
else
{
IngredientsCell* ingCell = (IngredientsCell*)[self.tableView dequeueReusableCellWithIdentifier:#"IngredientCell" forIndexPath:indexPath];
ingCell.ingredientNameLabel.text = self.selectedProduct.ingredientsArray[indexPath.row - 3];
if([self.selectedProduct.ratingsArray[indexPath.row -3] isEqual: #"4"])
{
ingCell.ingredientsImage.image = [UIImage imageNamed:#"icon_safe.png"];
}
else if([self.selectedProduct.ratingsArray[indexPath.row -3] isEqual: #"3"])
{
ingCell.ingredientsImage.image = [UIImage imageNamed:#"icon_low.png"];
}
else if([self.selectedProduct.ratingsArray[indexPath.row -3] isEqual: #"2"])
{
ingCell.ingredientsImage.image = [UIImage imageNamed:#"icon_med.png"];
}
else if([self.selectedProduct.ratingsArray[indexPath.row -3] isEqual: #"1"])
{
ingCell.ingredientsImage.image = [UIImage imageNamed:#"icon_high.png"];
}
else
{
ingCell.ingredientsImage.image = [UIImage imageNamed:#"icon_safe.png"];
}
return ingCell;
}
}
Code to alter cell height:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 0)
{
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:#"TitleCell"];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height + 1;
}
else if(indexPath.row == 1)
{
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:#"RatingCell"];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return 118;
}
else if(indexPath.row == 2)
{
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:#"IngredientHeaderCell"];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height + 1;
}
else
{
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:#"IngredientCell"];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return 60;
}
}
A segue will be performed automatically while a cell is tapped. Try the following code:
// - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
// {
// self.selectedIngredient = self.selectedProduct.ingredientsArray[indexPath.row - 3];
// [self performSegueWithIdentifier:#"ingViewSegue" sender:self];
// NSLog(#"selected ingredient %#", self.selectedIngredient);
// }
#pragma mark segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
IngredientWebViewController *webView = segue.destinationViewController;
webView.selectedIngredient = self.selectedProduct.ingredientsArray[indexPath.row - 3];
}

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];

Modal view controller segue from custom cell selection issue - iOS 7

I just recently noticed this issue in my app, and it seems to be an anomaly because I cannot pin down how/why it is happening, and there is no way to predict when. I have a custom UITableViewCell that I am loading into my UITableView subclass. I only have 5 cells in my tableView at all times, they are static and not prototypes. The issue I'm having is that sometime after I dismiss a modal view that I got to my selecting one of the cells, other cells become buggy. Here is what happens:
•Either I touch the cell and it performs the segue as planned
•About 10+ seconds after I touch the cell the segue is performed
•I touch the cell and nothing happens, but if I touch anywhere else on the view, the segue is performed
It is very very similar to the problem posted "Here" as well.
Here is my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//[super tableView:tableView didSelectRowAtIndexPath:indexPath];
//self.selectedObject = [self.objects objectAtIndex:indexPath.row];
NSLog(#"I DID SELECT path %ld", (long)indexPath.row);
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
if(indexPath.row == 0 && self.matchOneSetNum <= 3)
{
self.whereFrom = 1;
[self performSegueWithIdentifier:#"enterScoresSegue" sender:self];
}
if(indexPath.row == 1 && self.matchTwoSetNum <= 3)
{
self.whereFrom = 2;
[self performSegueWithIdentifier:#"enterScoresSegue" sender:self];
}
if(indexPath.row == 2 && self.matchThreeSetNum <= 3)
{
self.whereFrom = 3;
[self performSegueWithIdentifier:#"enterScoresSegue" sender:self];
}
if(indexPath.row == 3 && self.matchFourSetNum <= 3)
{
self.whereFrom = 4;
[self performSegueWithIdentifier:#"enterScoresSegue" sender:self];
}
if(indexPath.row == 4 && self.matchFiveSetNum <= 3)
{
self.whereFrom = 5;
[self performSegueWithIdentifier:#"enterScoresSegue" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"enterScoresSegue"])
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
UINavigationController *newView = (UINavigationController *)[segue destinationViewController];
EnterScoresViewController *enter = newView.topViewController;
enter.myDelegate = self;
enter.otherTeam = self.otherTeam;
if(self.whereFrom == 1)
{
enter.match = self.matchOne;
enter.setNumber = self.matchOneSetNum;
enter.matchOnePlayer = self.playerName;
}
if(self.whereFrom == 2)
{
enter.match = self.matchTwo;
enter.setNumber = self.matchTwoSetNum;
enter.matchTwoPlayer = self.playerNameTwo;
}
if(self.whereFrom == 3)
{
enter.match = self.matchThree;
enter.setNumber = self.matchThreeSetNum;
enter.matchThreePlayer = self.playerNameThree;
}
if(self.whereFrom == 4)
{
enter.match = self.matchFour;
enter.setNumber = self.matchFourSetNum;
enter.matchFourPlayers = self.playerStringsFour;
}
if(self.whereFrom == 5)
{
enter.match = self.matchFive;
enter.setNumber = self.matchFiveSetNum;
enter.matchFivePlayers = self.playerStringsFive;
}
}
}
There was an answer on a similar question that fixed the issue for me, here is the link: https://stackoverflow.com/a/23747207/2584268
And here is the full text:
After filling a Radar Apple responded with adding:
dispatch_async(dispatch_get_main_queue(), ^{});
To the end of the following method, which does the trick:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
In the method that presents the controller, you can schedule a no-op
block which will force the runloop to spin and there will be no delay.
Radar Ref: 15196237, feel free to file another and reference this.
wendrring if you segue in storyboard from a cell or from the ViewController(sender is self in this case), if from a cell the sender should be a cell too.
[self performSegueWithIdentifier:#"enterScoresSegue" sender:[self.tableView cellForRowAtIndexPath:indexPath]];

How to toggle UITableView Cell selected status

I have a UITableView with a custom Cell, the cell contains a UIImageView and a UILabel. Now When I load my table first time, It loads with a same image on each cell and different labels, which it takes from the LabelArray.
Now the image I am talking about is a radioButton, So when the user clicks the cell, the image changes. If user clicks again it changes to default state.
For this to happen, I have used this function and also I have declared a bool variable in my customcell class called selectionStatus.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell * cell = (CustomCell* )[tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row == 0)
{
if(cell.selectionStatus == TRUE)
{
//Do your stuff
cell.selectionStatus = FALSE;
}
else
{
//Do your stuff
cell.selectionStatus = TRUE;
}
}
if(indexPath.row == 1)
{
if(cell.selectionStatus == TRUE)
{
//Do your stuff
cell.selectionStatus = FALSE;
}
else
{
//Do your stuff
cell.selectionStatus = TRUE;
}
}
}
This works fine, (but I want to know whether it is a proper way, or can we check the cell.selected property) and I am able to get that effect. But now when I close the View and open it again the function
Edit based on below comments with #Anil
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.checkedIndexpath count] == 0)
{
[tableCell.selectionImage setImage:#"xyz.png"];
}
else
{
for (int i =0; i <[self.checkedIndexPath count]; i++)
{
NSIndexPath *path = [self.checkedIndexPath objectAtIndex:i];
if ([path isEqual:indexPath])
{
[tableCell.selectionImage setImage:#"abc.png"]
}
else
{
[tableCell.selectionImage setImage:#"xyz.png"]
}
}
return tableCell;
Regards
Ranjit
Another option for toggling UItableViewCells...
In the willSelectRowAtIndexPath return nil for NSIndexPath if cell is already selected, also set your _selectedIndexPath instance variable.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView.delegate tableView:self.tableView didDeselectRowAtIndexPath:indexPath];
indexPath = nil;
}
_selectedIndexPath = indexPath;
return indexPath;
}
In didSelectRowAtIndexPath and didDeselectRowAtIndexPath update your cell based on the property cell.selected ...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
// do stuff
} else {
// do stuff
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
// do stuff
} else {
// do stuff
};
}
and finally in viewDidLoad set the clearsSelectionOnViewWillAppear property...
- (void)viewDidLoad {
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
}
you have to save the index path of the selected row in didSelectRowAtIndexPath and check the index path in cellForRowAtIndexPath: set the corresponding image
Do you want multiple selection? try this...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell * cell = (CustomCell* )[tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row == 0)
{
if(cell.selectionStatus == YES)
{
[self.checkedIndexPaths addObject:indexPath];
//Do your stuff
cell.selectionStatus = NO;
}
else
{
[self.checkedIndexPaths removeObject:indexPath];
//Do your stuff
cell.selectionStatus = YES;
}
}
}
Edit
In cellForIndexPath check like this
// Set the default image for the cell. imageXYZ
for (NSIndexPath *path in self.checkedIndexPath)
{
if ([path isEqual:indexPath])
{
//set the changed image for the cell. imageABC
}
// no need of else part
}
Do the exact we will see
Take a boolean in your model class and update it on didSelectRow method and reload table. In cellForRowAtIndexPath check this like that.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
After making your cell check like that
ModelClass *yourModel=[self.yourArray objectAtIndex:indexPath.row];
if(yourModel.selection)
[cell.customImage setImage:[UIImage imageName:#"selected"];
else
[cell.customImage setImage:[UIImage imageName:#"un_selected"];
}
Check this link
https://github.com/adnanAhmad786/Quiz-View--TableView
First of all for toggling purpose declare a bool value selectionStatus in tableview cell class like this:
#property(nonatomic)BOOL selectionStatus;
Declare a NSMutableArray to store the selected indexpaths (for multi-selection purpose)
self.checkedIndexPaths = [[NSMutableArray alloc] init];
In didSelectRowAtIndexPath
a. if Bool value selectionStatus is No Insert indexPath to NSMutableArray checkedIndexPaths and set cell.selectionStatus = YES
b. if Bool value selectionStatus is Yes Remove indexPath from NSMutableArray checkedIndexPaths and set cell.selectionStatus = NO
c. Reload tableView each time
Find the code below :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
tableCell = [self.tableView cellForRowAtIndexPath:indexPath];
if(cell.selectionStatus == YES)
{
[self.checkedIndexPaths removeObject: indexPath];
cell.selectionStatus = NO;
}
else
{
[self.checkedIndexPaths addObject: indexPath];
cell.selectionStatus = YES;
}
[self.tablee reloadData];
}
In cellForRowAtIndexPath
a. First set cell image to unchecked i.e xyz.png here
[tableCell.selectionImage setImage:[UIImage imageNamed:#"xyz.png"]];
b. Set image as checked for all index paths in NSMutable array self.checkedIndexPaths
for (NSIndexPath *path in self.checkedIndexPaths)
{
if ([path isEqual:indexPath])
{
[tableCell.selectionImage setImage:[UIImage imageNamed:#"abc.png"]];
}
}

Search Bar with prepareForSegue for DetailViewController

I'm implementing the search bar for my project. The search part is ok. I can display the raw data and filter the data with the search text. When I tap on the cell of the search result tableView, it didn't transition to the detail view. But for the raw data I can transition to the detail view. I use the prepareForSegue method as I'm using storyboard.
Here's the code so far,
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString: #"Book Detail Segue"]) {
BookDetailsTVC *bookDetailsTVC = segue.destinationViewController; // for the detail view controller
bookDetailsTVC.delegate = self;
if (self.tableView == self.searchDisplayController.searchResultsTableView) { // The if block is not working
NSLog(#"Search Display Controller");
bookDetailsTVC.book = [self.searchResults objectAtIndex: self.searchDisplayController.searchResultsTableView.indexPathForSelectedRow.row];
} else {
NSLog(#"Default Display Controller");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
bookDetailsTVC.book = [self.objects objectAtIndex: indexPath.row];
}
}
}
When I tried using didSelectRowAtIndexPath method, I can transition to the detail view. But I got error message like that:
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
Unbalanced calls to begin/end appearance transitions for <BookDetailsTVC: 0x69b5300>.
Here's the code for didSelectRowAtIndexPath:
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath
{
BookDetailsTVC *bookDetailsTVC = [[BookDetailsTVC alloc] init];
if (tableView == self.searchDisplayController.searchResultsTableView) {
bookDetailsTVC.book = [self.searchResults objectAtIndex: self.searchDisplayController.searchResultsTableView.indexPathForSelectedRow.row];
[self performSegueWithIdentifier: #"Book Detail Segue" sender:self];
NSLog(#"Search Display Controller");
} else {
bookDetailsTVC.book = [self.objects objectAtIndex: indexPath.row];
[self performSegueWithIdentifier: #"Book Detail Segue" sender: self];
NSLog(#"Default Display Controller");
}
}
Thanks for help.
The problem is solved,
Change this in cellForRowAtIndexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
to
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier: CellIdentifier];
and in the prepareForSegue method, you can use the self.searchDisplayController.active to check the current tableview
if (self.searchDisplayController.active) {
NSLog(#"Search Display Controller");
bookDetailsTVC.book = [self.searchResults objectAtIndex: self.searchDisplayController.searchResultsTableView.indexPathForSelectedRow.row];
} else {
NSLog(#"Default Display Controller");
bookDetailsTVC.book = [self.objects objectAtIndex: self.tableView.indexPathForSelectedRow.row];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
self.selectedPerson = [self.searchResults objectAtIndex:indexPath.row];
PersonasDetalle *pd = [self.storyboard instantiateViewControllerWithIdentifier:#"PersonaDetalle"];
pd.persona = self.selectedPerson;
[self.navigationController pushViewController:pd animated:YES];
}
}

Resources