self.navigationController pushViewController: animated: gives me a black screen - ios

I'm using Objective-C. I have this code in my .m file.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
detailViewController *detail = [[detailViewController alloc]init];
[self.navigationController pushViewController:detail animated:YES];
}
And I created my Detail View Controller Scene in storyboard. It looks like this [
And every time I run this in my simulator and tap on one of the tableview cell, it pushes the screen to a complete black screen like this:
Can someone help me? I would thank you very much!

Yes it will give a blank screen, because you haven't attached any visual interpretation on detailViewController class.
Use this method
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
DetailViewController *vc = [sb instantiateViewControllerWithIdentifier:#"detailViewController"];
[self.navigationController pushViewController:vc animated:YES];
You will have to set storyboard id by clicking on view controller and set storyboard id as shown in picture
Note : for above pic replace Storyboard id "MessagingVC" with "detailViewController"

When using a storyboard, you don't want to use alloc+init to create the view controller. Instead, you need to assign a Storyboard ID in Interface Builder and then use:
[self.storyboard instantiateViewControllerWithIdentifier:my_identifier];
A better option may be to set a push segue on the table view controller. This will cause the instantiation and push to happen automatically. You can override prepareForSegue:sender: to set properties, if needed.

Related

Opening ViewController programmatically

I have another ViewController inside the same story board to which I want to switch by clicking a button. The problem is when I try to control-Drag the second view controller to create an Outlet inside the ViewController.m file of the primary viewcontroller, an outlet isn't created.
In Android we can open a new Activity with different UI from inside of another activity. I am sure same can be achieved in iOS as well, so my question is how can I create an outlet of the second view Controller and open it programmatically?
It is not possible in iOS to create an IBOutlet from one ViewController to another ViewController, But you can use a UIStoryboardSegue for the purpose.
I will suggest you to follow Tutorial: Storyboards from Apple Documentation. It will help you understand how ViewControllers are actually connected.
Opening SecondViewController programmatically is possible by using Storyboard Identifier, You need to provide storyboard identifier name for the class you want to switch to, see this image , in my demo i have used secondViewController
Now use this code inside your buttonClick event method.
- (IBAction)buttonClicked:(id)sender {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
SecondViewController *secondViewController = (SecondViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"secondViewController"];
// Use this to show your UIViewController in modal transition.
[self presentViewController:secondViewController animated:YES completion:nil];
// Use this to show your UIViewController in push transition with navigation controller
//[self.navigationController pushViewController:secondViewController animated:YES];
}
Try this
Viewcontroller*homeVC;
[self.navigationController setNavigationBarHidden:YES];
UIStoryboard *storyBoard;
storyBoard=[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
homeVC=(HomeVC*)[storyBoard instantiateViewControllerWithIdentifier:#"HomeVC"];
[self.navigationController pushViewController:homeVC animated:YES];
As others mentioned, you cannot do this.
To override and launch VC and keep it's properties you can:
First, create segue between viewControllers: Zoom out the view by double clicking the background of interface builder. Ctrl+drag from one VC to another and choose type of segue (e.g. show).
Than create action for button, in which you can:
[self performSegueWithIdentifier:#"myIdentifier" sender:self];
After that, in -(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender check identifier of segue, set new yourCustomClassViewController and voila!
if ([segue.identifier isEqualToString:#"myIdentifier"]) {
myCustomClassViewController *myCustomVC = [segue destinationViewController];
myCustomVC.oldProfile = newProfile;
}

Dynamically build a menu with a TableViewController in Objective-C

I am quite new to Objective-C and Xcode so I don't really know how to handle a dynamic menu with TableViews.
I am generating Table Rows and want to load an other ViewController by clicking at the rows.
I have tried to link the row to a NavigationController and wanted to load the furthers views there with:
NSString * storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"Fremdbearbeitung"];
[self presentViewController:vc animated:YES completion:nil];
but I have problems that the view is not in the view hierarchy at the moment. Also I don't know to tell there dynamically which instantiateViewControllerWithIdentifier should be loaded by passing information from the rows.
Can you give me tips how to handle that best practice?
Can I tell the table rows at they are initialized where they should linked when they are clicked?
Thanks in advance.
EDIT: Found a way that works for me:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
testclass *test = [self.array objectAtIndex:indexPath.row];
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"Main"
bundle:nil];
UIViewController* vc = [sb instantiateViewControllerWithIdentifier:test.second];
[self.navigationController pushViewController:vc animated:YES];
}
So i can dynamically go to the view with identifier which i gave to the function in my object test and property second.
I don't need a extra navigation controller for that, because i can do that in my main TableView.
Is this a good way?
You want to push the viewController and not present it. It will push the view controller onto the navigation controller’s stack and updates the display.
Read the Concepts clearly again. Also Learn about Storyboards and segues.
Also the ViewController Programming Guide.
Also you will find tons of tutorials for all the basics you want to learn, use Google like crazy..!
Edit : Using Storyboard Segues

Attempt to present a viewcontroller whose view is not in the window hierarchy

I have a tab bar application. My requirement is I select the 'scan' tab to scan the qr code and navigate/jump immediatley to another 'list' tab. Both 'scan' and 'list' tab are there in the viewControllers array in didFinishLaunchingWithOptions After referring this link, i don't think i need to set the delegate as both the tabs are already present in the hierarchy.
I get this warning in the following line
if(x)
{
listViewCntrl = [[ListViewController alloc] initWithNibName:#"ListViewController" bundle:nil];
listViewCntrl.getFlag = YES;
[self presentViewController:listViewCntrl animated:YES completion:Nil]; // I get the warning here
}
If I comment out the above code and add
[self.tabBarController setSelectedIndex:1];
then I would not be able to get the subView of the listViewController (set flag to show the subview) which i need to display inside the list tab after scanning.
App crashes if I add
[self.tabBarController setSelectedViewController:listViewCntrl];
So how do I display the listView's subview after scanning?
You can try this if you use storyboard:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewController * destViewController = [storyboard instantiateViewControllerWithIdentifier:#"ViewControllerIdentifier"];
[self.navigationController pushViewController:destViewController animated:YES];
You have to set an identifier for your controller in your storyboard.
ListViewController *listController = (ListViewController*)[self.tabController viewControllers][1];
listController.getFlag = 1;
[self.tabBarController setSelectedIndex:1];
The problem is that you're creating an entirely new ListViewController. You say you already have one in the tab controller - you don't need a new one.
You can't use your 3rd option because, again, the two ListViewController's are different objects (they may be of the same class, but they point to a different address).

Initiating a segue from uiview or uivewcontroller that is not on storyboard

How can I initiate segue from a custom UIView or custom UIViewController that is not on Storyboard? - they are created programmatically inside a parent UIViewController.
Although the destination UIViewController is on the storyboard.
Then just do it the old fashioned way. Instantiate it and present it modally or just push it if you are in a navigation controller. Hope this helps.
EDIT:
You can talk about segue only if it is in the storyboard. If Your source View Controller is not in it, you just present the next one as I said. You can instantiate your destination view controller from the storyboard:
MyViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"MyViewController"];
[self presentViewController:controller animated:YES];
From this point you will be "back in the storyboard" so you can perform segues in the destination View Controller.
First give storyboard id. Select the view controller than write a identifier(Storyboard ID)
Secondly, just open your .m file then write belove codes.
UIStoryboard * st = [UIStoryboard storyboardWithName:#"nameOfStoryboard" bundle:nil];
MyViewController *viewController = [st instantiateViewControllerWithIdentifier:#"YourStoryboardID"];
[self.navigationController pushViewController:viewController animated:YES];
Last line of code. Might also be
[self presentModalViewController:viewController animated:YES];

Linking a new viewcontroller to Storyboard?

There is probably a simple solution but I can't figure it out.
I am using storyboards for the interface.
I start with a tab bar controller, but before the user is allowed to use the app the user has to authenticate himself trough a loginview which is modally pushed at the start.
I want to configure the loginview at the same storyboard, but I can't seam to figure out how to link the view controller at the storyboard and my code.
What I have done:
Create a new UIViewController subclass trough file > new > new file.
Drag a new UIViewController in the story board
Set the class in the custom class tab
drags a UILabel for test purpose.
run
No label...
Pull on a new UIViewController that will act as the login view controller onto the MainStoryboard. In the attribute inspector change the identifier to LoginViewController (or something appropriate). Then add
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentModalViewController:vc animated:YES];
}
to the First view controller and the login screen will be loaded from your storyboard and presented.
Hope this helps.
The answer by Scott Sherwood above is most correct answer I found after lot of searching. Though very slight change as per new SDK (6.1), presentModalViewController shows deprecated.
Here is very small change to above answer.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
HomeViewController * hvc = [sb instantiateViewControllerWithIdentifier:#"LoginView"];
[hvc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:hvc animated:YES completion:nil];
I'm new in this field. But if the first view controller is a navigation view controller and its rootviewcontroller is a table view controller. If you want to push a view controller like the LoginViewController when you click the cell, and you also want to go back to the table view by using the navigation bar. I recommend this way:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *controller = [sb instantiateViewControllerWithIdentifier:#"LoginViewController"];
[self.navigationController pushViewController:controller animated:YES];
}
In this way, you can have the navigation.
By the way, I don't know why this kind of problem you asked will appear. I guess when the loginviewcontroller is created in the code, its view is not the view in the storyboard. If someone know the cause, please tell me! thanks!

Resources