Hi guys i am a beginner on Obj c Programming, I have created a "self segue"(segue to same view controller) from a tableviewcell. Now my problem is, i am setting few parameters in the prepareForSegue method, but somehow the segue already happens before this method is called(i am not even calling "performSeguewithIdentifier"). I understand that this might be because the segue is associated with the cell. But i found no other way to create a "self-segue"
please help.Btw i am using xcode6..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_selctdObj = [avObjArray objectAtIndex:indexPath.row];
if([_selctdObj isContainer])
{
[self performSegueWithIdentifier:#"isContainerSegue" sender:self];
}
else
{
[self performSegueWithIdentifier:#"isItemSegue" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"isContainerSegue"]) {
// Get destination view
serverBrowseVC *sbvc = [segue destinationViewController];
[sbvc setServerSelected:_serverSelected];
[sbvc setBrowseObjID:_selctdObj];
}
}
Now invariably "isContainerSegue" gets executed ,even is the object is not a container. i also tried commenting the
//[self performSegueWithIdentifier:#"isContainerSegue" sender:self];
But every time "isContainerSegue" gets executed..
You said you weren't calling performSegueWithIdentifier, but you are. You shouldn't be if you've connected the segue from the cell. You also shouldn't implement didSelectRowAtIndexPath at all, just prepareForSegue. You can get the indexPath from the sender argument (the sender will be the cell) of prepareForSegue:sender:. If you're having a problem with the "if [_selctdObj isContainer]" clause, you need to post what isContainer does.
Related
I have a controller with a listview that contain a custom cell.
I have created a modal segue from the cell to the next controller and I gave a name to this segue but when I click on the cell, prepareForSegue isn't called.
I could use the didSelectRowAtIndexPath and performSegueWithIdentifier but I have to send data to the next controller from the cell I've clicked on.
Any idea why the prepareForSegue isn't called? Or how to send data to the controller with another method?
You can get the cell data in didSelectRowAtIndexPath by getting the cell from the index of customCell that you clicked, and after you can performSegueWithIdentifier.
So let's make this easier:
Under your didSelectRowAtIndexPath method, add this line to get the properties of your customCell
YourCustomCell *customCell = (YourCustomCell *)[self.tableView cellForRowAtIndexPath:indexPath];
So now if you have something stored under your customCell you can access it from customCell instance.
After you managed to store or manipulate your data from customCell you do the performSegueWithIndenfier:
[self performSegueWithIdentifier:#"yourSegueID" sender:self];
Hope this helps
When you connect a segue from a cell to another view controller, unless it's a static table view, you'll have to trigger performSegueWithIdentifier from the didSelectRowAtIndexPath
After you execute performSegueWithIdentifier, prepareForSegue would be called.
In prepareForSegue, you can set up your destination view controller, which you can access via segue.destinationViewController
Like so:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[super prepareForSegue:sender sender:sender];
if ([segue.identifier isEqualToString:#"YOUR_SEGUE_NAME_HERE"]) {
UIViewController *destinationViewController = segue.destinationViewController;
}
}
Or if you need to set things up in the didSelectRowAtIndexPath , you could do (iOS7+ only)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"YOUR_SEGUE_NAME_HERE" sender:self];
UIViewController *destinationViewController = [self.transitionCoordinator viewControllerForKey:UITransitionContextToViewControllerKey];
}
Update:
Turns out #rdelmar is correct, it does work with dynamic cells.
All you have to do then is
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[super prepareForSegue:sender sender:sender];
if ([segue.identifier isEqualToString:#"YOUR_SEGUE_NAME_HERE"]) {
NSIndexPath *selectedIndexPath = [self.tableView indexPathForCell:sender];
}
}
And you have the index path of the cell that was tapped. Then you can use that to query your datasource and find the object that was used to populate that cell.
I'm trying to pass some data between UIViewControllers in a storyboard. I have some code below to pass the data. Whne I log the string that i'm saving on the original screen it's fine, but when I go to the UIDetailViewController the go is returning (null). What's my issue??
Original View Controller:
-(void)tableView:(UITableView *) tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView==_countryTableView) {
if (indexPath.section==0) {
AthleteDataTransfer *dataTransfer = [[AthleteDataTransfer alloc] init];
dataTransfer.name=#"Yo";
dataTransfer.dob=#"01/01/2000";
dataTransfer.description=#"I am awesome";
dataTransfer.hometown=#"Launy";
NSLog(#"%#", dataTransfer.name);
[self performSegueWithIdentifier:#"showDetail" sender:self];
}
}
}
Detail View Controller:
AthleteDataTransfer *dataTransfer = [[AthleteDataTransfer alloc] init];
_name.text=dataTransfer.name;
dataTransfer.dob=_dob.text;
dataTransfer.description=_description.text;
dataTransfer.hometown=_hometown.text;
NSLog(#"%#", dataTransfer.name);
Insted of passing data in tableViews didSelectRowAtIndexPath, pass the data in prepareForSegue method.
Like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetail"]) {
AthleteDataTransfer *dataTransfer = (AthleteDataTransfer *)[segue destinationViewController];
dataTransfer.name=#"Yo";
dataTransfer.dob=#"01/01/2000";
dataTransfer.description=#"I am awesome";
dataTransfer.hometown=#"Launy";
}
}
You should use prepareForSegue method to accomplish this.
and if you have more than one segues from this ViewController you can use segue.Identifier to distinguish
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if(segue.identifier==#"yoursegueidentitifer")
{
DetailedViewController *detailController = [segue destinationViewController];
detailController.nameoftextview.text =self.textViewName.text;
}
}
As suggested in other answers out here you should pass data in the prepareForSegue method. I'am not going to repeat the same code here. I wanted point out one thing that you dont want to create the DetailViewController again in the detailViewController like below
AthleteDataTransfer *dataTransfer = [[AthleteDataTransfer alloc] init]; // This is wrong and not required at all
NSLog(#"%#", dataTransfer.name);
Instead you should use self to refer the current controller
NSLog(#"%#", self.name); // This would be enough
For posting the text data to your destination View Controller, you can use the prepareForSegue method like this.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
DestinationViewController *destController = [segue destinationViewController];
destController._yourTextView.text == _yourText.text;
}
}
Here, DesctinationViewController is the controller to which you want to pass the values and in the next step, you assign the values by using its object and the properties declared on that controller.
Since you are using performSegueWithIdentifier, this will automatically call prepareForSegue after performSegueWithIdentifier is executed which will show up your destination View Controller.
I have a popover segue that goes to a view controller. I want to set some properties in the view controller when a cell is clicked. I tried using -prepareForSegue:, but then I realized that it doesn't have the scope of the selected cell. I know that I have to use:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
delegate method, but I'm not sure how that will affect the popover segue. Do I have to programatically create the popover, or is there another way?
Thanks much!
~Carpetfizz
Use self.tableView.indexPathForSelectedRow to get the data from your table's data source, e.g., the array backing the table data. If, for some reason, you don't want to get the data from your data source, then the sender is the UITableViewCell that was tapped to trigger the segue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueID"]) {
YourDestinationViewControllerClass* destinationController = segue.destinationViewController;
destinationController.somePublicProperty = self.yourTablesDataSourceArray[self.tableView.indexPathForSelectedRow.row];
UITableViewCell *cell = (UITableViewCell *)sender;
destinationController.someOtherPublicProperty = cell.textLabel.text;
}
}
So add an NSIndexPath propriety to your VC. Let's call it selectedCell. In your tableView:didSelectRowAtIndexPath method, save the selected index path to the instance variable.
Then in your prepareForSegue method, use the instance variable.
Alternately, in your prepareForSegue method, you could ask the table view for the currently selected row using the table view's indexPathForSelectedRow method.
The best approach is to use the indexPathForSelectedRow property.
For example you can write a code like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifier"])
{
NSIndexPath *indexPath = [sender indexPathForSelectedRow];
NextViewController *vc = (NextViewController *)segue.destinationViewController;
vc.yourProperty = #"Some Value";
}
}
Assuming NextViewController as your segue destination controller and yourProperty as the property you want to set during the segue, you can access and set information from your parent controller because indexPathForSelectedRow automatically knows which cell has been clicked.
More information can be found here.
I am getting this error when I try to preform a segue...
2012-11-14 20:24:54.133 MyApp[26266:c07] nested push animation can result in corrupted navigation bar
2012-11-14 20:24:54.486 MyApp[26266:c07] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2012-11-14 20:24:54.487 MyApp[26266:c07] Unbalanced calls to begin/end appearance transitions for <SheetDrillDownViewController: 0xa1bb980>.
Here is my setup: Initial view --> next view (UITableView) --> last view (UITable)
Each cell pushes to another view until the last view. I do not have a modal segue, i have a push segue... I have the push segues linked from the cell to the next view, each with different names... I have a perform segue line in my selectedRowAtIndex method. I have tried removing that method, with people saying I am double calling the segue, but then the cell when clicked turns blue, and doesn't push to anywhere... How can I fix this error? Thanks.
Here is my code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath) {
[self performSegueWithIdentifier:#"subjectDrillDown" sender:nil];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"Attempting to identify segue...");
// Make sure we're referring to the correct segue
if ([[segue identifier] isEqualToString:#"subjectDrillDown"]) {
NSLog(#"Segue has been identified...");
// Get reference to the destination view controller
SubjectDrillDownViewController *vc = [segue destinationViewController];
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
NSMutableDictionary *object = [tableDataSource objectAtIndex:selectedIndex];
NSString *key = [object valueForKey:#"key"];
[vc setSelectedItem:key];
NSLog(#"Switching to %# detail view...",key);
NSLog(#"Passing dictionary to %# view... (Source below)\n\n %#",key,[NSString stringWithFormat:#"%#", [tableDataSource objectAtIndex:selectedIndex]]);
[vc setDetailDataSourceDict:[tableDataSource objectAtIndex:selectedIndex]];
}
else {
NSLog(#"ERROR, DOUBLE CHECK SEGUE'S NAME!");
}
}
I have seen all of the other Stack Overflow questions, but most of the correct answers don't work for me...
EDIT:
The next view is able to load, but when I click the back button, there are suddenly two more views...
UPDATE:
I will try to post the number of times Attempting to identify segue... NSLogs, but my compiler suddenly won't run :(
You surely don't need to perform segue in didSelectRowAtIndexPath, if you have already configured it like cell -> next view.
But, removing the call from there doesn't work for you then you can try the segue from view controller (ctrl+drag from view area) to next view and keep the segue call in didSelectRowAtIndexPath
I always use one of the following methods
Method 1:
Segue from UITableViewCell to Next View Controller
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Nothing
}
Method 2:
Segue from Main View Controller to Next View Controller
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"subjectDrillDown" sender:nil];
}
The error you are getting is because you have segue and you perform the segue manually when selected - hence, it is resulting in nested push animation
Make sure the name of the segue is correct and you are using ONLY one of the above methods
This is my first iPad/Storyboard/SplitViewController and it has a table as the master and each row is a separate document for the detail view. I am starting from the Xcode 4.2 template.
I have gotten the iPhone half to work. I hooked up a segue from the tableviewcell and get the call:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
And with that I can bring up the detail view correctly.
On the iPad storyboard, I don't get the prepareforsegue call. I have tried creating a segue between the masterviewcontroller and then tried the tableviewcell controls but can't get it to call my prepareforsegue.
I also tried:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"segueDetailIpad" sender:nil];
}
That will call my Segue, but the tableview doesn't have an indexPath set. (It is set on the iPhone though).
Also, when I switchback to the iPhone version, it wants to call the same performseguewithidentifier (as above), but then I have to switch between different #"segueDetailIpad" parameters.
It seems to me I am mixing "old" and "new" models and need to find some way to
get the iPad to use the segue and not rely on the didSelectRowAtIndexPath.
Hope this is enough for some suggestions ;-)
thx!
Just as user589310 said I was able to solve my similar problem by embedding the [segue destinationViewController] in a UINavigationController.
For example:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue destinationViewController] class] == [UINavigationController class])
{
[[[[segue destinationViewController] viewControllers] objectAtIndex:0] setDelegate:self];
}
else
[[segue destinationViewController] setDelegate:self];
}