I'm totally new to iOS programming. I only programmed on Android so far and Objective-C is a total different and new language for me now.
What I want to do is to not use a design that I've created with the storyboard. I want to do all programmatically, since I think it will be more dynamic if I do it like this.
The problem I'm encountering is, that I want to have 3 different views. I googled a bit, and stumbled upon some stackoverflow questions. There, people suggested using a NavigationController. Okay. Now I'm trying to implement it. What I want to have is the following
A MainViewController that has 3 different views. The first view is a loginView. The second one is displaying data and the third is displaying detailed data dependent on the click of the second view.
Is a navigationcontroller corerct for this? The problem I'm having is where I tell the app that I want to start with the MainViewController and push the LoginView in it.
I have a MainViewController.h and MainViewController.m that are subclasses of UIViewController
Now, where exactly do I do this? I have the didFinishLaunchingWithOptions method right here with the following content
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
UIViewController *viewController = [[MainViewController alloc]init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[navigationController pushViewController:viewController animated:NO];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
But that just crashes the app. What am I doing wrong? How do I get those three views? Am I starting completely wrong? Please help. As I said I'm new to iOS development. It's easy for me to programm on one view. I did that already, but I want thre different views! Thanks!
A MainViewController that has 3 different views. The first view is a loginView. The second one is displaying data and the third is displaying detailed data dependent on the click of the second view.
That's wrong.
You need three different view controllers, each of those will manage its own view.
Then you push one after another in the navigation controller, depending on user interaction.
Yes, Gonzalo Aune is rite, You should not push the rootviewcontroller in NavicationController.
Also , I will Suggest you to keep your first view (Login View) out of Navigation controller.
You can start with your MainViewController and based on check and conditions you can present LoginView on MainViewController using
[self presentViewController:loginViewController animated:YES completion:NULL];
And after successful login you can dismiss LoginViewController.
Remove this:
[navigationController pushViewController:viewController animated:NO];
You shouldnt push the ViewController since you told the NavigationController already that the ViewController would be the root one:
UINavigationController *navigationController = [[UINavigationController alloc]
initWithRootViewController:viewController];
use this code and if application is universion then use same code else remove the condition of ([[UIDevice currentDevice] userInterfaceIdiom]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UINavigationController *navController;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
{
if(result.length>0)
{
for(var i in result)
{
var ObjResult=result[i];
var content = "<div data-role='collapsible' id='set" + i + "'>";
content+="<h3>"+ObjResult.title+"<br>";
var intDate=parseInt(ObjResult['ordered date']);
content +=timestampToDate(intDate)+"</h3>"
if(isNaN(ObjResult.med_placeorderfor))
content+="<p><a>Medicle Place order for: </a>"+result[i].med_placeorderfor+"</p>";
if(isNaN(ObjResult.pres_placeorderfor)>0)
content+="<p><a>Medicle Place order for: </a>"+result[i].placeorderfor+"</p>";
if(ObjResult['order status'].length>0)
content+="<p><a>Order status: </a>"+ObjResult['order status']+"</p>";
if(ObjResult.comments.length>0)
content+="<p><a>Comments: </a>"+ObjResult.comments+"</p>";
content+="</div>";
}
$("#id_notification_list_dashboard").append( content ).collapsibleset('refresh');
$("#id_notification_list_dashboard").trigger('create');
}
else
{
$("#id_notification_list_dashboard").append("<div style=\"text-align:center\" data-role='list-divider'><h1>No data found</h1></div>").collapsibleset('refresh');
}
$('body').removeClass('ui-loading');
loadingWithMsg("hide");
}
} else {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil];
}
navController=[[UINavigationController alloc]initWithRootViewController:self.viewController];
[navController.navigationBar setTranslucent:YES];
navController.navigationBar.tintColor = [UIColor colorWithRed:161.0f/255.0f green:18.0f/255.0f blue:6.0f/255.0f alpha:1];
self.window.rootViewController =navController ;
[self.window makeKeyAndVisible];
return YES;
}
Related
I'm having trouble calling a newly created view controller within the storyboard. I have created an app using the default master-detail template. The only simple thing I'd like to do is call a new View Controller window when a specific check is valid/invalid (depending on requirement) (I refuse to use the term "Login" :-) ).
What is the best location to do this? In here (appDelegate)?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
UINavigationController *masterNavigationController = splitViewController.viewControllers[0];
MasterViewController *controller = (MasterViewController *)masterNavigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
} else {
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
MasterViewController *controller = (MasterViewController *)navigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
}
//Should I call the new view controller object from my storyboard at this location? (i.e. myView)
return YES;
}
I'm even considering starting all over without using the template of Xcode.
Do you need to use different controllers depending on check result?
If yes than there are few suggestions. You can cover your view with some activity view which covers all screen, wait for checking and than remove activity view.
Another thing you can try is making another view controller in storyboard and move starting arrow to it. You can try to login and after it perform correct segue.
And at least i can suggest to create root view controller programmatically.
something like this.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
levelViewController = [[LevelViewController alloc] init];
window.rootViewController = levelViewController;
[window makeKeyAndVisible];
}
Any way to know the navigation source?
For example, the navigation stack has A/B/C three view controllers.
If C is popped, when B is displayed, any way to know the navigation is from C to B ?
Thanks a lot in advance.
in another simple method
first declare the UINavigationController in Appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:self.viewController];
self.window.rootViewController = nav;
[nav setNavigationBarHidden:YES];
[self.window makeKeyAndVisible];
return YES;
}
after that in your first view controller.m import the second view controller header file
#import "B.h"
in your button action
- (IBAction)butvie:(id)sender {
B*tab=[[Balloc]init];
[self.navigationController pushViewController:tab
animated:YES];
}
in C viewcontroller comes to back of B
- (IBAction)butvie:(id)sender {
[self.navigationController popViewController
animated:YES];
}
You can track this manually. You can keep a global variable in your AppDelegate class and set that variable whenever you pop a particular viewController.
UPDATE after comments:
In this case, you can use NSUserDefaults or you can post an NSNotification object from the poppedViewController. Though I am not sure, how much efficient these options are for you to use.
You can tell whether a controller appeared because it was added to the stack, or because another controller was popped off the stack using isMovingToParentViewController. If you have this code in B, it will tell you which happened:
-(void)viewDidAppear:(BOOL)animated {
if ([self isMovingToParentViewController]) {
NSLog(#"Coming from A");
}else{
NSLog(#"Coming from C");
}
}
I have been playing around with this for a couple of days and I cannot figure this out.
-> Basically I want to implement a simple login view that has a button when clicked, goes to go to the navigation controller ( in my case is "viewController" with buttons that link to mini math games which are other views).
-> Login screen should be displayed first, than navigation controller's root view when a button is clicked on the login screen
-> I have tried to declare the navigation controller when I click the button of the login screen but that seems to not work
-> Is it safe to say that a navigation controller can only be initialized in the apple delegate?
Currently I have this in my apple delegate declaring and setting my navigational controller:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navigationViewController = [[UINavigationController alloc] initWithRootViewController:self.viewController]; // self.viewController is the main screen
self.window.rootViewController = navigationViewController; // set root to navigationViewController
[self.window makeKeyAndVisible];
return YES;
}
Any ideas will be appreciated. Thank you for your time !
Your code in the app delegate looks ok. NavigationController does not need to be declared in the AppDelegate. In your case, it is definitely ok to declare it upon login button pressed.
Try this at the login event:
UIViewController *nextVC = [[UIViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:nextVC];
[self presentViewController:navController animated:YES completion:^{
}];
What I would do would be set the loginViewController as the rootViewController of the navigation. And after check if login was done successfully, you could implement [self performSegueWithIdentifier:#"identifier"] setting the game viewController as destination. (Using Storyboard would make your life much easier). Well, that's my opinion :)
I just recently started programming for iOS/iPhone. I thought I knew what I was doing until XCode5/iOS7 came around. Previously, I created a class derived from UIViewController with a XIB, added a label, and programatically added it to the rootWindow:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
... // boilerplate code
MyViewController* myRoot = [[MyViewController alloc]init];
self.window.rootViewController = myRoot;
To use a navigation bar, I changed the code slightly:
MyViewController* myRoot = [[MyViewController alloc]init];
UINavigationController* navigationController = [[UINavigationController alloc]init];
[navigationController pushViewController:myRoot animated:YES];
self.window.rootViewController = navigationController;
This seemed to work fine. However, on iOS 7 the controls at the top of my custom view controller appear to be behind the navigation bar. Some googling resulted in this link which describes changes in the status bar.
It also seems to indicate that,
A) UINavigationController should handle the changes automatically
B) "auto layout" should handle the changes automatically,
and that I shouldn't need to worry. However, my sample app above doesn't appear to handle anything automatically.
I also found some other sample code which uses the controller differently: adding the navigation controller's view as a subView to an existing view. This sort of makes sense for adding a navigation controller later on in an app's lifetime, but I am trying to set one up on launch.
Am I using the UINavigationController correctly?
What do I need to consider for iOS7 vs. earlier versions?
How do I configure "Auto Layout" (I don't see this in interface builder anywhere)?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
I have a tab bar application in Xcode 4.3 and I'm trying to insert a login screen before the tabbar is shown. The app works OK if presentModalViewController has animated:YESbut if it is without animation the view is not showing.
#synthesize window = _window;
#synthesize tabBarController = _tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
LogInViewController *logViewController = [[LogInViewController alloc] initWithNibName:#"LogInViewController" bundle:nil];
[self.window addSubview:_tabBarController.view];
[self.tabBarController presentModalViewController:logViewController animated:YES];
//This wont work
//[self.tabBarController presentModalViewController:logViewController animated:NO];
[self.window makeKeyAndVisible];
return YES;
}
-(void)loginDone{
NSLog(#"back to the app delegate");
[self.tabBarController dismissModalViewControllerAnimated:YES];
}
Is this the right way to do it?
Why wont the code work with animated:NO ?
I also get this on output Unbalanced calls to begin/end appearance transitions for <UITabBarController: 0x689d350>.
First of all, move [self.window makeKeyAndVisible]; before your view controller setup.
Additionally, you should be presenting the modal view controller within the viewWillAppear: method of the view controller that will be visible first, to make sure your apps view hierarchy has been fully initialized before presenting your login screen.
Don't do this:
[self.window addSubview:_tabBarController.view];
Do this:
self.window.rootViewController = _tabBarController;
This will put the tabBarController on the screen. But that's not exactly what you want... My advise is:
1) Start by putting the logViewController has the rootViewController as I showed you above.
2) Once you got what you want (login is successful) just tell the AppDelegate to switch the rootViewController. This can be done in with delegation or notifications.
Also, as Toastor indirectly pointed out, you should start the presentViewController from the UIViewController who actually initiates it (and not from the AppDelegate).