ObjectiveC > Segue between TableView and ViewController - ios

I'm a beginner in Objective C and I have an issue between my Table View Controller and ViewController. When I click on the cell nothing happens, I don't go in my view controller to have more details about my cell.
I use a push segue and I don't forget to give it an identifier and to do this code part in my TableView:
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetails"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *destViewController = segue.destinationViewController;
destViewController.details = data [indexPath.row];
}
}
My link between my two views is between the cell prototype and the ViewController window.

in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"showDetails" sender:self];
}
in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showDetails"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *destViewController = segue.destinationViewController;
destViewController.details = data [indexPath.row];
}
}

Related

Pass data from Table View Cell to a View Controller in IOS

I know this question is asked many time , i had searched a lot and tried many solution but not worked. I have made a customize table view in which data is load from a service. The data load is quite limited , i have to show the detail of data into new view controller when user click on a cell. Its should pass data of the respective cell which carries data. I have tried segue technique to pass data to new vc but fails , its shows null in value which i'm passing. I have created some labels in new vc in which i'm calling the values from table view cell. My code is,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"ShowDetail"]) {
//Do something
ShowViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
destViewController.tites = [_Title objectAtIndex:indexPath.row];
destViewController.prce = [_Price objectAtIndex:indexPath.row];
NSLog(#"PPPP is %#",destViewController.phon);
destViewController.ara = [_LandArea objectAtIndex:indexPath.row];
destViewController.phon = [_Phone objectAtIndex:indexPath.row];
destViewController.citi = [_City objectAtIndex:indexPath.row];
destViewController.loc = [_location objectAtIndex:indexPath.row];
destViewController.tye = [_type objectAtIndex:indexPath.row];
destViewController.Idss = [_Id objectAtIndex:indexPath.row];
destViewController.nam = [_name objectAtIndex:indexPath.row];
destViewController.emal = [_email objectAtIndex:indexPath.row];
destViewController.roomss = [_rooms objectAtIndex:indexPath.row];
destViewController.wash = [_washroom objectAtIndex:indexPath.row];
destViewController.flloors = [_floor objectAtIndex:indexPath.row];
destViewController.stat = [_status objectAtIndex:indexPath.row];
destViewController.descrp = [_descrip objectAtIndex:indexPath.row];
destViewController.countryy = [_country objectAtIndex:indexPath.row];
}
}
Issue in this question is that you are not populating the _Price and other arrays properly, so where you are populating _Title array , fill other arrays as well like _Price, _City
An outlet doesn't instantiate because an outlet is a variable (or property).
The objects in a nib are instantiated when that nib is loaded, and they are assigned to each outlet as immediately as possible afterward, after the objects are created but before awakeFromNib is sent to all relevant objects.
In your case you can pass data in ShowViewController and update the label in ShowViewController's viewDidLoad or viewDidAppear.
Define string in ShowViewController interface as
#property (strong, nonatomic) NSString * titesStr;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"ShowDetail"]) {
//Do something
ShowViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
destViewController.titesStr = [_Title objectAtIndex:indexPath.row];
....
....
....
}
}
In ShowViewController viewDidAppear update your label as
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
tites.text = titesStr;
}
In place of passing data one by one you can use array also. Best implementation would be using model class.
EDIT
[self performSegueWithIdentifier:#"ShowDetail" sender:tableView];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"ShowDetail"]) {
//Do something
UITableView *tv = (UITableView*)sender;
ShowViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = [tv indexPathForSelectedRow];
destViewController.tites = [_Title objectAtIndex:indexPath.row];
....
....
....
}
}
Make following changes in your code :
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"ShowDetail" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowDetail"])
{
ShowViewController *destViewController =(ShowViewController *) segue.destinationViewController;
NSIndexPath *indexPath = (NSIndexPath *)sender;
destViewController.tites = [_Title objectAtIndex:indexPath.row];
destViewController.prce = [_Price objectAtIndex:indexPath.row];
// use this indexpath for segue
}
}

No responed after pressing UICollectionViewCell in the UICollectionViewController

when I come the part of sending image from UICollectionViewController to another ViewController here is View A:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Detail Segue"])
{
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
NSIndexPath *path = [[self.collectionView indexPathsForSelectedItems] lastObject];
Photo *selectedPhoto = self.photos[path.row];
PhotoDetailVC.photo = selectedPhoto;
}
}
and I receive it in the ViewController (View B) using:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.imageView.image= self.photo.image;
}
I think the problem is that you didn't call performSegueWithIdentifier:sender: in any place in code which actually responsible for triggering navigation not prepareForSegue:sender: which is called when preparing for the navigation
so I suggest to implement collectionView:didSelectItemAtIndexPath: as the following
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
Photo *selectedPhoto = self.photos[path.row];
// this line is the one that is responsible for navigation
[self performSegueWithIdentifier:#"Detail Segue" sender:selectedPhoto];
}
and modify prepareForSegue:sender: as the following
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Detail Segue"]) {
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
PhotoDetailVC.photo = sender;
}
}

Touch cell and open a new view controller

The following code is in my menuViewController.m. Now I want to go to another view when touch on a specific cell. What should I do to go to contactViewController?(I am using storyboard)
storyboard image:
https://drive.google.com/file/d/0BwOYR2GMJ7l8U1lYYVFVTWVkOG8/edit?usp=sharing
code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row==2)
{
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Set the title of navigation bar by using the menu items
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: #[dvc] animated: NO ];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
};
}
I want to go to another view when touch on a specific cell.
For this, I'd do it this way:
Step 1:
Drag from TableViewController to ContactViewController:
Step 2:
Select segue and specify the Segue Identifier (Show attributes Inspector tab in the right side bar)
I have named the Segue Identifier as SegueTestID
I chose Push as my style but it seems you might need Modal
And the corresponding code (in your MenuViewController.m) should be something like:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 2) {
[self performSegueWithIdentifier:#"SegueTestID" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//following lines needed only if you need to send some detail across to ContactViewController
if ([segue.identifier isEqualToString:#"SegueTestID"]) {
ContactViewController *destinationViewController = segue.destinationViewController;
destinationViewController.strTest = #"Check";
//where strTest is a variable in ContactViewController. i.e:
//"#property (nonatomic, strong) NSString *strTest;"
//declared in `ContactViewController.h`
}
//...
}
PS: It seems you have alot in your -prepareForSegue: already.
Obviously... you'll need to hook things up properly.
In Storyboard , Do this ( In your case its contactviewcontroller ) give the name identifier name to contactViewController whatever you want as shown in image for showRecipeDetail
and you can go to the contactviewcontroller
and then
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
destViewController.recipe = [recipes objectAtIndex:indexPath.row];
}
}
In above method it shows how to pass the data from current viewcontroller to destviewcontroller
where We simply set the property (i.e. recipeName) in the RecipeDetailViewController to pass the recipe name. Obviously, you can add other properties in the detail view controller to pass other recipe-related values. ( In your case it will be data you want to pass to contactviewcontroller)
When a segue is triggered, before the visual transition occurs, the storyboard runtime invokes prepareForSegue:sender: method of the current view controller. By implementing this method, we can pass any needed data to the view controller that is about to be displayed. Here, we’ll pass the selected recipe object to the detail view controller.

Transfering NSString from prototype cell not working with prepareForSegue

I am just trying to transfer a simple string from a UILabel in a prototype cell into a label in the next View Controller. Value of label.text in the viewDidLoad of the View Controller is returning (null).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
mainCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (mainCell == nil) {
mainCell = [[dictionaryTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString* date = [dateArray objectAtIndex:indexPath.row];
mainCell.viewLabel.text = date;
return mainCell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
ViewController *one = segue.destinationViewController;
one.label.text = mainCell.viewLabel.text;
}
}
What am I doing wrong here?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
NSLog(#"View Load Segue Success");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewController *one = segue.destinationViewController;
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
}
And actually, assigning text to text label you should do in your viewController one's method(viewDidLoad or viewWillAppear). So, you need to make a property in viewController one for transferring NSString.
You can use indexPathForSelectedRow:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"View Segue"]) {
ViewController *one = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Or you can also use sender if your segue is from the cell to the next scene, e.g.:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"View Segue"])
{
ViewController *one = segue.destinationViewController;
NSAssert([sender isKindOfClass:[UITableViewCell class]], #"Not cell");
UITableViewCell *cell = sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
one.textProperty = [dateArray objectAtIndex:indexPath.row];
}
}
Two things to note:
As a matter of good programming style, I am not retrieving the text value from the cell. I'm retrieving the text value from the model. You should not be relying upon the view for information to be passed along. Go back to the model, the original source of the information.
Do not set the text property of the label in the destination controller directly. The controls of the destinationController have not been created yet. You should defer setting controls until the destinationController's viewDidLoad. So, instead, create a NSString property in the destination controller:
#property (nonatomic, strong) NSString *textProperty;
Clearly, you should use a more descriptive name than textProperty, but hopefully you get the idea. Anyway, prepareForSegue can set this new property and the viewDidLoad of the destination controller should then use that NSString property to populate the text property of the UILabel, e.g.:
- (void)viewDidLoad
{
[super viewDidLoad];
self.label.text = self.textProperty;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
YourViewController *controller =[[YourViewController alloc] init];
[self presentModalViewController:controller animated:YES];
one.label.text = [dateArray objectAtIndex:indexPath.row];
}
Change the label.text after presentModalViewController. Now what happens?
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
I understand you are already using Segue. You should follow the other answer.

Send indexPath.row to another UIViewController

So I have the didSelectRowAtIndexPath method into a UITableViewController.
The TableView goes to a UIViewController which is controlled by a NavigationController.
I want to send the indexPath.row to the class called by the NavigationController, is there any way to send a parameter to another class?
My app scheme is:
TabBarController ---> NavigationController ---> TableViewController ---> UIViewController
If you are using storyboard:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UITableViewCell *cell = sender;
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Pass any objects to the view controller here, like...
[vc setIndexPath:indexPath];
}
}
else
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
YourViewController *vc = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
[vc setIndexPath:indexPath];
}
}

Resources