I have 3 cells in a UITableView. Person, Car and House and I want each one to segue to a custom and different STATIC TableViewController so the user can do some setup.
What is the most efficient way to go about this?
In prepareForSegue do I query and call the method didSelectRowAtIndexPath then do what?
Or in the storyboards do I setup a push segue from one cell to a separate TVC, 3 times?
Does anyone know of any good tutorial? I dont know how to go about this thanks.
I am guessing you are using storyboards? Are the cells static cells, and always in the same order?
If so I am guessing you have a UIViewController or UITableViewController in the storyboard which is populated with Person, Car, and House.
You then have 3 different view controllers that you wish to navigate to depending on which of Person, Car or House is selected?
As you are using prototype cells, I would do the following:
As previously mentioned, when creating the cell do:
[cell setTag:indexPath.row];
then in didSelectRowAtIndexPath do the following:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
switch ([cell tag]) {
case 0:
PersonDetailViewController *personDetailViewController = [[self storyboard] instantiateViewControllerWithIdentifier:#"PersonDetails"];
[[self navigationController] pushViewController:personDetailViewController animated:YES];
break;
case 1:
// Do similar for Car
breal;
case 2:
// Do similar for House
default:
break;
}
You can do like this:
In your didSelectRowAtIndexPath method, do this:
if(indexPath.row == 1)
{
// push to controller 1
}
else if(indexPath.row == 2)
{
// push to controller 2
}
else if(indexPath.row == 3)
{
// push to controller 3
}
First Connect your main tableview with three individual TVC and add segue for each add identifier for that
then in didSelectRowAtIndexpath check which indexpath has been pressed and call that viewController like below
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.row == 1)
{
[self performSegueWithIdentifier:#"view1" sender:self];
}
else if(indexPath.row == 2)
{
[self performSegueWithIdentifier:#"view2" sender:self];
}
else if(indexPath.row == 3)
{
[self performSegueWithIdentifier:#"view3" sender:self];
}
}
Then in prepareforSegue find which one view is called
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"view1"]){
TableView1 *tableMenu = segue.destinationViewController;
}
else if([[segue identifier] isEqualToString:#"view2"]){
TableView2 *tableMenu2 = segue.destinationViewController;
}
else if([[segue identifier] isEqualToString:#"view3"]){
TableView3 *tableMenu3 = segue.destinationViewController;
}
}
Hope this works if any mistake someone correct me thnx
Related
I am currently making a tableView for my app, and I've got my cells from a .plist file. However I want to be able to enter my second view controller no matter, what cell I click on, the difference should be that the UIText for my second viewController will depend on which cell I click.
So far, I have imagined something like;
if(tableview.tag == 1){
myUIText.text = #"a";
}else if(tableview.tag == 2){
myUIText.text = #"b";
etc.......
Will this work using the same view controller, same UIText? If not, then how?
And how can I set the tags for my array in my .plist file?
I would appreciate your answers
EDIT: Here is a sample of two methods;
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.items count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * id = #"plistdata";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:id forIndexPath:indexPath];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:id];
}
cell.textLabel.text = self.items[indexPath.row];
return cell;
}
More information is certainly needed by I will make some assumptions on your code and see if it helps any. I assume the the text you want to send is the title of the cell the person clicked on. Now how you send that to the next VC will differ depending on if you are using a segue or not. If you are using a segue you can do something like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"mySegue"]) {
UITableViewCell *cell = (UITableViewCell *)sender;
UpcomingViewController *viewController = segue.destinationViewController;
viewController.textView.text = cell.chapterText;
}
}
However if you are using didSelectRowAtIndexPath then:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UpcomingViewController *viewController = [[UpcomingViewController alloc] init];
viewController.textView.text = self.arrayOfChapterText[indexPath.row];
[self.navigationController pushViewController:viewController animated:YES];
}
Now again because your question wasn't very clear on your scenarios I have taken some liberties with what I think you are probably trying to do. I assume that the view controller that will show after you choose an item will have the UITextView as a public property so that you can set it before pushing or segueing to your new view. I also assume in the didSelectRowAtIndexPath that you are using a UINavigationController.
Hope this helps.
I have a UITableView which has 3 rows. the first row calls a phone number when pressed, which is working fine.
I have two other UIViewControllers which I would like to be displayed when the respective row is selected in the UITableView.
Below is my didSelectRow method.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//deselect row
[tableView deselectRowAtIndexPath:indexPath animated:YES];
switch (indexPath.row)
{
case 0:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel:1800333000"]];
break;
case 1:
break;
case 2:
break;
default:
break;
}
}
As can be seen, I've set up my switch expression. Im trying to figure out how to call the other two UIViews.
Could someone please provide the code required to display these views?
Your question is not exactly clear about what exactly you are doing but I think what you need is to make a segue and specifically a segue from a UITableViewCell.
First thing to do is control-click and drag a connection from your UITableView cell to the other view in the storyboard. This should create a line between the table view cell and the next view with a little circle. Click on that circle to set and edit the segue properties in the properties inspector. Then in the UITableViewController class you need to have a prepare for segue method. Here is some example code that I've written, its got an extra if statement in there because I actually had 2 UITableViews - one from the UITableViewController and one from the searchbarviewcontroller (which was within the UITableViewController).
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([sender isKindOfClass:[UITableViewCell class]]) {
NSIndexPath * SBidxPath = [self.searchDisplayController.searchResultsTableView indexPathForCell:sender];
NSIndexPath * TBidxPath = [self.tableView indexPathForCell:sender];
NSIndexPath * idxPath = [[NSIndexPath alloc] init];
if (!SBidxPath) {
idxPath = TBidxPath;
}
else{
idxPath = SBidxPath;
}
if ([segue.identifier isEqualToString:CELL_PUSH_SEGUE_ID]) {
if ([segue.destinationViewController isKindOfClass:[YTViewController class]]) {
[self prepareYTViewController:segue.destinationViewController withDictionaryEntry:[self.dictionaryEntries objectAtIndex:idxPath.row]];
}
}
}
}
The other thing is that you also need to look into what a NSIndexPath is. Typically the property that you use from that structure is the .row property.
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];
I am working in a small app that connects with sqlite. It brings the data to list in the tableview without any problems, but when click in the cell to display details, it does not work and errors are not found.
this is the code how I call the UIviewController with identifier:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Report11ViewController *destino = [self.storyboard instantiateViewControllerWithIdentifier:#"visualizacion"];
Vehiculo *tmp = [vehiculos objectAtIndex:[indexPath row]];
destino.vehiculo = tmp;
[self.navigationController pushViewController:destino animated:YES];
}
I put in Attributes inspector identifier: visualizacion
Please any help will be appreciate. thanks
try to use this code:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"get it some name"]) {
UITableViewCell*cell = (UITableViewCell*) sender;
NSIndexPath*ip = [self.tableView indexPathForCell:cell];
Vehiculo*tmp = [vehiculous objectAtIndex:ip.row];
Report11ViewController *destino = (Report11ViewController*)segue.destinationViewController;
destino.vehiculo = tmp;
}
}
But be sure that your segue to Report11ViewController have identifier same as in that code (get it some name)
You need setup "StoryboardID" in Identity inspector, not Attributes.
And Report11ViewController VC must be in the same storyboard as you table view.
So, using storyboard you can create a segue from the UITableViewCell from the first tableViewController to a detailViewController.
Not too complicated, however, when a UISearchBarDisplayController is introduced into the storyboard mix, how can you segue the results cell to the detailViewController?
I am able to search without a problem, I followed this tutorial: http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
All I can do is select a row from the search, it turns blue and doesn't go to the detailViewController.
I have implemented the method prepareForSegue, which works for the non searched cells, but can't figure out this one.
Here's the solution that's based on the comment by #James Chen. Also using a different IndexPath depending on which state the table is in.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toDetail"]) {
Person *person = nil;
if (self.searchDisplayController.active == YES) {
NSIndexPath *indexPath = indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.filteredPersonArray objectAtIndex:indexPath.row];
}
else {
NSIndexPath *indexPath = indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.personArray objectAtIndex:indexPath.row];
}
[[segue destinationViewController] setPerson:person];
}
}
I tried your solution and found that prepareForSegue is called twice
due to the life cycle and didSelect... -> performSegueWithIdentifier.
self:prepareForSegue: object on destination controller is set
(with wrong index) because
dest:viewDidLoad: the destination controller view is loaded after which
self:didSelectRow...: the index is known and properly set.
self:prepareForSegue: object is now correct but has no side effect.
I then focused on didSelect... and came up with this solution where I deleted the segue and pushed the view programmatically:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DestTableViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"DestViewController"];
CustomObj *custObj = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
custObj = [filteredListContent objectAtIndex:indexPath.row];
} else {
storeToDetail = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
controller.custObj = custObj;
[self.navigationController setNavigationBarHidden:NO];
[self.navigationController pushViewController:controller animated:YES];
// presentViewController::animated:completion is always full screen (see problem below)
}
I then experienced some problems going back because I follow a segue
from a mapView, which lead to:
//DestinationViewController
- (IBAction)back:(id)sender
{
[self.navigationController popToRootViewControllerAnimated:YES]; // list
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; // map
}
which is not the way to do it but for now it works.
However, the first part is easy and clean, and maybe it works for you too?!
Ok I think I got it, it seems like a bit of a hack but it works for my purposes:
I am using storyboard:
I have a UITableview controller with UISearchBarDisplayController directly on top of it. No code just drag and drop.
From there, I followed this tutorial to get the search bar to search correctly http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
However prepareForSegue: would only let me display a cell from the original array, not with the search array.
So I used didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (savedSearchTerm) {
searchRowSelected = indexPath.row; //<-- the trick that worked
[self performSegueWithIdentifier:#"ShowDetail" sender:self];
}
}
searchRowSelected is an int variable that I declared at the top of the class.
didSelectRowAtIndexPath: knew which row I was selecting, but prepareForSegue didn't. Thats why I needed that variable.
This is how I used it in prepareForSegue:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"ShowDetail"]) {
dvc = [segue destinationViewController];
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
int row = [path row];
if (savedSearchTerm){ //set the detailViewController with the searched data cell
myDataClass* c = [searchResults objectAtIndex:searchRowSelected];
dvc.myDataClass = c;
}else{ //set the detailViewController with the original data cell
myDataClass* c = [array objectAtIndex:row];
dvc.myDataClass = c;
}
}
}
Also use this code to clean up savedSearchTerm
-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{
[self setSavedSearchTerm:nil];
}
If anyone has a better solution I'm all ears :)