I have a tableview which is showing my array items. . I connected push style segue to detailviewcontroller screen with my storyboard but i dont want to all items go detailviewcontroller so i made a controller like that ;
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if (sender == self.btnEkle) return;
if (sender == self.btnKrediKartlarim) return;
NSString *bankaAdi = [[mainList objectAtIndex:indexPath.row] objectForKey:#"BankaAdi"];
if (bankaAdi.length > 1) {
KartDetay *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"KartDetay"];
[self presentViewController:vc animated:YES completion:nil];
}
If bankaAdi.length > 1 my app should go to the KartDetay
if its not i mean else my app should go to the detailviewcontroller
these codes are working but there is an error in my compiler.
Unbalanced calls to begin/end appearance transitions for .
Sorry for my English i know i didn't describe myself clearly but please try to help me.
Thanks !
---UPDATED AREA----
First of all Thank you for answer.But it doesnt work or i couldnt do that.
1- I created 2 manuel different segues to my KartDetay("taksit" segue name) and my DetayEkran("detay" segue name)..
2-I used with these codes..
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *indexPath2 = [self.tableView indexPathForSelectedRow];
bankaAdi = [[mainList objectAtIndex:indexPath2.row] objectForKey:#"BankaAdi"];
if (bankaAdi.length > 1)
{
[self performSegueWithIdentifier:#"taksit" sender:nil];
}
else
{
[self performSegueWithIdentifier:#"detay" sender:nil];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"taksit"])
{
//if (sender == self.btnEkle) return;
//if (sender == self.btnKrediKartlarim) return;
KartDetay *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"KartDetay"];
[self presentViewController:vc animated:YES completion:nil];
}
else
{
DetayEkran *detayEkran = [self.storyboard instantiateViewControllerWithIdentifier:#"DetayEkran"];
[self presentViewController:detayEkran animated:YES completion:nil];
}
When I run my app and tap my first cell which is bankaAdi>1.
App can go to KartDetay screen but my compiler says :
Unbalanced calls to begin/end appearance transitions for .
Thank you for answer again.
----ReUpdated Area --- problem is solved by Greg... Thank you for that Greg...
I made a huge mistake with these codes coz i call another DetayEkran *detayEkran = [self.storyboard instantiateViewControllerWithIdentifier:#"DetayEkran"];
[self presentViewController:detayEkran animated:YES completion:nil];
in my prepareforsegue method. When i delete all instantiate codes in my prepareforsegue methods my app working fine...
So
Greg codes are working like a charm.. Thank you Greg !
When the segue is called the prepareForSegue:segue method is called and it handles the transition, you shouldn't call presentViewController or push view controller manually.
The best way to do that is create two segue for KartDetay and detailviewcontroller with two different identifiers in storyboard.
And override didSelectRowAtIndexPath method, where you check your condition and run appropriate segue:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *bankaAdi = [[mainList objectAtIndex:indexPath.row] objectForKey:#"BankaAdi"];
if (bankaAdi.length > 1) {
[self performSegueWithIdentifier:#"YOUR1IDENTIFIER" sender:nil]
}
else
[self performSegueWithIdentifier:#"YOUR2IDENTIFIER" sender:nil]
}
If you need to pass any parameters use prepareForSegue method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"YOUR1IDENTIFIER"]) {
KartDetay *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"KartDetay"];
[self presentViewController:vc animated:YES completion:nil];
}
else {
//handle other view controller
}
}
Just remember to replace segue identifiers with your one.
The prepareForSegue:sender: method is invoked before opening the detail view controller. It is the place to prepare for the transition, not to present/push view controllers. The actual transition is done after the method has been invoked. Whether push or present is used, depends on the segue type in the storyboard.
Try using the tableView:didSelectRowAtIndexPath: method instead of the prepareForSegue:sender: method. This should solve your problem.
Related
I have created a screen containing two table views where i have successfully called the method cellForRowAtIndexPath but now am facing trouble in navigating to the other page from tableview option by using didSelectRowAtIndexPath.I think am doing some mistake and i have clearly no idea what is the next step.Can anyone guide how should i do it?? I have used this code-
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([tableView isEqual:leftTableView]) {
TattooSinglesScreen *obj=[self.storyboard instantiateViewControllerWithIdentifier:#"TattooSinglesScreen"];
EyecatcherScreen *obj1=[self.storyboard instantiateViewControllerWithIdentifier:#"EyecatcherScreen"];
TattooToplist *obj2=[self.storyboard instantiateViewControllerWithIdentifier:#"TattooToplist"];
int i=indexPath.row;
if(i==0){
[self.navigationController pushViewController:obj animated:nil];
}
else if (i==1) {
[self.navigationController pushViewController:obj1 animated:NO];
}
else if (i==2) {
[self.navigationController pushViewController:obj2 animated:NO];
}
}
else {
TattooSinglesScreen *obj=[self.storyboard instantiateViewControllerWithIdentifier:#"TattooSinglesScreen"];
EyecatcherScreen *obj1=[self.storyboard instantiateViewControllerWithIdentifier:#"EyecatcherScreen"];
TattooToplist *obj2=[self.storyboard instantiateViewControllerWithIdentifier:#"TattooToplist"];
int i=indexPath.row;
if(i==0){
[self.navigationController pushViewController:obj animated:nil];
}
else if (i==1) {
[self.navigationController pushViewController:obj1 animated:NO];
}
else if (i==2) {
[self.navigationController pushViewController:obj2 animated:NO];
}
}
}
If you want to navigate from table view to another view controller don't set animated:NO.set animated:YES for navigating.But if you set animated:NO,definitely it does not navigate.So you have to do following things for navigating.
YourViewController *yourVC = (YourViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"StoryBordIdentifier"];
[self.navigationController pushViewController:yourVC animated:YES];
Also You can use in this didSelectRowAtIndexPath
[self performSegueWithIdentifier:#"segueID" sender:self];
with
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
YourViewController *vc = segue.destinationViewController;
}
Click Table Row and Go another Page
Segue or didSelectRowAtIndexPath
Making Push Segue when table row is selected
I see user3182143's answer helped, but for what it's worth I've set up a tiny demo project (now updated with two tables) to show anybody interested how it's done.
It also illustrates (as the name implies), that you can, indeed, push manually and set the animation parameter to NO, just run it in the simulator.
I can't tell why that didn't work in your original approach, pri, but my guess is that you set up your navigation view controller wrongly somehow.
For code & storyboard readability I'd recommend using segues anyways.
I'm a very beginner to iOS development. I made a navigation application in iOS to view some details in another view when table view cell tap. I did the following code,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
LawyerViewController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:#"LawyerViewController"];
NSLog(#"%#",[self.myObject objectAtIndex:indexPath.row]);
dvc.lawyer = [self.myObject objectAtIndex:indexPath.row];
[self.navigationController pushViewController:dvc animated:YES];
}
This is going to the next view. But dvc.lawyer is not null here. It's null on Next View page.
Reading the Value in Next page
NSLog(#"%#",self.lawyer.firstName);
How can I fix this.
Thanks in Advance!
You are supposed to instantiate ViewControllers in another way, if you use storyboard segues. You need to implement prepareForSegue where you can Access the segues destinationViewController like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// reference to the destination view controller
LawyerViewController *vc = [segue destinationViewController];
// Pass any data
vc.lawyer = self.myObject[[self.tableView indexPathForSelectedRow].row]; // Not tested
}
}
Up until now I have used prepareForSegue method to notify a view controller he is about to review a segue from a different view controller, but if i'm the vc that sending the segue, will my prepareForSegue (in he same class of the segue sender) will check if there is a code to preform before he fires the segue?
I'm asking because I got a solution here to preform a simple segue just to go from stable view row which represent notes to the creation page of the note for editing...very simple, but from some reason it's not presenting my note in the creation page, only takes me to a new clean creation page..
So I though maybe it's because the prepareForSegue method..here you can see the question to give you more details How to to create a segue to push back to editing mode from a table view?
Would really appreciate to get your help on this.
This are the 2 methods I added to my NotesList table view controller:
#pragma mark - delegate
- (void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"noteSegue" sender:nil];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"noteSegue"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NMNote *note = [self.notes objectAtIndex:indexPath.row];
NMCreateNotesViewController *destination = [segue destinationViewController];
destination.textField.text = note.content;
}
}
And I made sure the segue identifier in the storyboard is named noteSegue. So why its note working...Im getting a new TextView instead of populating it with the note content :/
This is the error i'm getting:
Thanks!
The prepareForSegue: method is called on the current VC not the destination. UIViewController Class Reference. You can use the method to obtain a reference to the destination VC and set variables/call methods on it before the segue is performed.
Calling the segue like this:
[self performSegueWithIdentifier:#"NAMEOFSEGUE" sender:nil];
You can then prepare the destination VC like this:
#import "NMCreateNotesViewController.h"
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"NAMEOFSEGUE"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
[destination createNote]; /* or something similar */
}
}
EDIT:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NMNote *note = [self.notes objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"noteSegue" sender:note];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"NAMEOFSEGUE"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
NMnote *note = (NMNote*) sender;
destination.textField.text = note.content;
}
}
To check if there is a code to preform before the segue you can use solution below:
if ([segue.destinationViewController isKindOfClass:[UIViewController class]]) {
UIViewController *nextVC = segue.destinationViewController;
if(nextVC respondsToSelector:#selector(yourMethod)){
[nextVC yourMethod];
}
}
You can check if you are sure to perform the specific segue by implementing this method
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
If you have your note presenting code in viewDidLoad, try moving that to viewDidAppear (in your note editing VC). There used to be an issue when presenting from a TableView row where the segue would fire after VDL was executed.
So I have a problem when trying to push some Viewcontrollers basically when the app loads it checks if you are already registered and if you are it sends you to a diff vc and if your not registered it sends you to a RegisterVC. It's done in storyboard and the problem is that when I put the code in viewDidLoad the pushes works but I can't see the rootviewcontroller from the storyboard but if I move the code into the init with coder I can see the viewcontroller but the push return's nil in the method that's supposed to push to a new vc, so the transition never happens.
The code looks like follows:
if (emp == nil) {
[self gotoRegisterView];
}
else {
[self gotoSMWView];
}
and :
- (void) gotoRegisterView {
UIViewController* vc = [self.storyboard instantiateViewControllerWithIdentifier:#"RegisterVC"];
[self.navigationController pushViewController:vc animated:YES];
}
- (void) gotoSMWView {
UIViewController* vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SMWVC"];
[self.navigationController pushViewController:vc animated:YES];
}
Any suggestions are much appreciated.
If you're using storyboards, just connect the main scene to any other scene you want to call from there. Then, Ctrl+Drag from the initial VIEW CONTROLLER (not elements on the view controller, but from the controller itself). Then click on the segues you just created and give them good descriptive names. For this example, we'll just say segue1 and segue2.
Now, if segue1 takes you to the RegisterView, and segue2 to SMWView then you can do this:
- (void) gotoRegisterView {
[self performSegueWithIdentifier:#"segue1" sender:self];
}
- (void) gotoSMWView {
[self performSegueWithIdentifier:#"segue2" sender:self];
}
If you need to do any other initialization or set up on these view controllers, you can override this method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
Within this method, you can check which segue has been called using this template:
if([[segue identifier] isEqualToString:#"segue1"])
And you can get an instance of your destination view controller like this:
YourViewController *vc = [segue destinationViewController];
My segues were added in the storyboard. I want push to a viewController, say Deep_VC, different from the next one in the storyboard, say Next_VC. I'm using:
Deep_VC *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"DeepVC"];
[self.navigationController pushViewController:controller animated:YES];
It goes there, but I get errors. The nav bar tile is for the Next_VC, not the Deep_VC, and the error messages:
Finishing up a navigation transition in an unexpected state . . .
Unbalanced calls to begin/end appearance transitions . . .
My prepareForSegue looks like:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"toNextVC"]) {
Next_VC *vc = [segue destinationViewController];
vc.receivedData = [NSMutableArray arrayWithObjects:passData, nil];
}
if ([[segue identifier] isEqualToString:#"toDeepVC"]) {
Deep_VC *vc = [segue destinationViewController];
vc.receivedData = [NSMutableArray arrayWithObjects:passData, nil];
}
}
Can anyone help, please?
I'd rather use performSegue instead of pushViewController in your case. But wait, if you`ve wired your VCs in the storyboard you don't need to push. This will be done automagically by the segue.
EDIT
if (login == successful) {
[self performSegueWithIdentifier:#"toNextVC" sender:self];
} else {
[self performSegueWithIdentifier:#"toDeepVC" sender:self];
}
After that prepareForSegue will be called automatically and there you set your data. pushViewController is not needed as the seque pushes the appropriate VC.
Hope that helps!