I'm building an application which has a TabBarController at the top level. Contained within one of the tabs there is a tableview, and when a row is selected, I'd like to go to a set of 5 views, controlled via a UIScrollViewDelegate and UIPageControl.
I've built a basic app with the UIScrollViewDelegate and UIPageControl, based Derek Bredensteiner's code in this answer: How do I use UIPageControl to create multiple views?
It works fine as a stand alone application, ie: when the ViewController code is called directly from the AppDelegate via:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
But when I try to call the same code from my tableview code, I am getting a black screen. I've also tried using presentModelViewController and I get the UIPageViewControl dots but the rest is black.
LearnPageViewController *phoneContentController = [[LearnPageViewController alloc] init] ;
// [self presentModalViewController:phoneContentController animated:YES];
[self.navigationController pushViewController:phoneContentController animated:YES];
I managed to get it to work by adding a new window property #property (nonatomic, retain) IBOutlet UIWindow *window; but it doesn't sound right. There is a window property up on the AppDelegate and now another one 2 levels down.
Related
if we are using storyboards to deliver the interface setting in out ios app, then the AppDelegate.m will be quite clean and the only thing we are caring about is making our logic code enter at the viewDidLoad() function in the viewController which we hooked with a storyboard.
And there is a way that wildly used when we choose not to load the storyboard and make our window ourself at Application didFinishLanchingWithOption method of AppDelegate.m like this:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController *viewController = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
the document says there should be a window and a rootViewController for our app to present stuff on the screen.
But if we are using the storyboard, who did this stuff for us? I mean things like creating the window and assign the rootViewController?
And can we choose what kind of rootViewController when using storyboard?
And once a rootViewController is assigned, can we choose to replace that?
Mostly I am asking how did all the stuff organized under hook
I'm not using a storyboard or anything. I'm just creating the cocoa classes and linking them up individually. I can get to load up the default View Controller which is SplashViewController but i can't get past there.
I have experience in php, android programming and python, but i'm totally clueless on how Obj-C and how the iOS framework works :(
SplashViewController.m
-(void)initializeInterface
{
//Initialize start button
[self.startButton addTarget:self action:#selector(startActivity) forControlEvents:UIControlEventTouchDown];
//Initialize fading backgrounds
[self animateImages];
}
-(void)startActivity
{
PhoneViewController *phoneView = [[PhoneViewController alloc] initWithNibName:#"PhoneViewController" bundle:nil];
[self.navigationController pushViewController:phoneView animated:YES];
}
SplashViewController.h
#import <UIKit/UIKit.h>
#import "PhoneViewController.m"
#class PhoneViewController;
#interface SplashViewController : UIViewController
#property (strong, nonatomic) PhoneViewController * phoneViewController;
#property UIImage *splashbg1;
#property UIImage *splashbg2;
#property (nonatomic, retain) IBOutlet UIImageView *splashbg;
#property (nonatomic, retain) IBOutlet UIButton *startButton;
-(void)initializeInterface;
-(void)animateImages;
-(void)startActivity;
#end
EDIT
classAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
//Move from delegate view controller to root view controller
self.window.rootViewController=[SplashViewController new];
[self.window makeKeyAndVisible];
return YES;
}
Wrap your splash view controller in a navigation controller.
Otherwise, the navigationController property of your splash view controller is nil and pushViewController has no effect.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController: splashViewController];
To move from one UIViewController to other UIViewController, you can try the following things
If SecondViewController *secondViewController is the UIViewController you want to move in to, then your can do the following:
[self presentViewController: secondViewController animated:YES completion:nil];
This is when you UIViewController is not embedded inside a UINavigationController.
It is possible to create your view controllers entirely in code without using Storyboards or XIB files, but it's not recommended. It's like trying to write a complex user application in assembler. The state of the art has evolved since the days when that was necessary. There are better tools. Use them.
Creating everything yourself is both quite complex and not very well documented. You are setting yourself up for a very frustrating, error-prone process. I've been doing iOS development pretty much full time since 2009, and I would not attempt this.
That being said, if you are a masochist, you would create your view controller using initWithNibName:bundle:, passing in nil for both parameters, and then implement the loadView method. In loadView you're create your view hierarchy and install it.
If you are new to iOS/Objective-C, DO NOT DO THIS. It is like trying to write a kernel device driver in machine code as your first foray into UNIX.
Change you AppDelegate method as below -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
UINavigationController *navcon = [[UINavigationController alloc]initWithRootViewController:[SplashViewController new]];
//Move from delegate view controller to root view controller
self.window.rootViewController=navcon;
[self.window makeKeyAndVisible];
return YES;
}
Problem in your code, you have not taken any navigationController, that enables you push or pop UIViewController. Doing above you can use your method -(void)startActivity to Start a new ViewController.
I'm implementing PKRevealController in an existing project. This project uses Storyboards, but user is able to play Cocos2D 2.0 game within the app.
My problem is that when user goes out of Cocos2D, I use a notification (notification center) on my navigation controller (that controls the Cocos2D game) to segue to my main view, but when it does the segue the PKRevealController doesn't work anymore.
I implement the PKReveal on my AppDelegate, so I suppose I should (somehow) implement it somewhere i can re-implement it when i exit a Cocos2d game.
Any ideas? Thank you!
If anyone has the same problem, there's how I solved this problem:
Created a new UIViewController in Storyboard, and embed it in a NavigationCotroller
Created my InitialViewController for this new ViewController and implemented both <PKRevealing, UIApplicationDelegate>.
Created thise properties in it:
#property (nonatomic, strong) PKRevealController *revealController;
#property (strong, nonatomic) UINavigationController *myNavController;
#property (strong, nonatomic) UIWindow *window;
On viewDidLoad did self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; (like on my AppDelegate)
Finally on viewDidAppear method:
FrontViewController *frontViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"FrontViewController"];
PortraitAppNavigationController *frontNavigationController = [[PortraitAppNavigationController alloc] initWithRootViewController:frontViewController];
LeftMenuViewController *leftViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"LeftMenu"];
// Step 2: Instantiate.
self.revealController = [PKRevealController revealControllerWithFrontViewController:frontNavigationController leftViewController:leftViewController];
// Step 3: Configure.
self.revealController.delegate = self;
self.revealController.animationDuration = 0.25;
// Step 4: Apply.
self.window.rootViewController = self.revealController;
[self.window makeKeyAndVisible];
I've been making an App completely programmatically, but I would like to add some more buttons etc.
Currently my main view is a full-screen TableView.
I would like to load a UIView (from a NIB) which has some buttons / labels and my curreny TableView in the middle (full width) with sort of a header and footer with my buttons / labels.
(Since I suspect that changed need to be made here...) My AppDelegate currently has the following code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
AFViewController *viewController = [[AFViewController alloc] initWithStyle:UITableViewStylePlain];
//AFViewController *viewController = [[AFViewController alloc] initWithNibName:#"mainView" bundle:nil];
self.viewController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
You need to create a UIViewController instead of UITableViewController. You can easily do in your current AFViewController which actually a UITableViewController, just follow these steps
Open AFViewController.h change UITableViewController to
UIViewController.
Then open AFViewController.xib and add a
UIView from controls.
Drag UITableView inside UIView.
Right click File Owner connect view to the UIView and create IBOutlet for the UITableView inside the UIView.
Thats it you are ready to go.. And at last..
AFViewController *viewController = [[AFViewController alloc] initWithNibName:#"AFViewController" bundle:nil];
Why don't you create the desired structure in one nib itself? Create a nib with view controller. On the nib place your buttons and tableview as per your layout.
Interface builder is intended to reduce your coding effort when it comes to design so use it. Make sure to make your new view controller as the root controller in app delegate.
I have a project which I don't really understand the views and navigation behind. I start out in the AppDelegate (MAAppDelegate), where I define properties:
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UIViewController *detailViewController;
Then in the MAAppDelegate.m, I create a navigationController, and
#implementation MAAppDelegate
#synthesize detailViewController;
#synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Init the navController for the Master Detail View of the grade cells
UINavigationController *navController = [[UINavigationController alloc] init];
detailViewController = [[UIViewController alloc] init];
UIViewController *viewController = [[MAController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
So at this point, I think I have a working naviationController, I've setup an instance of a custom UIViewController (custom class MAController) and I've set it up as the rootViewController.
Then, in my MAController class, the class where I do all of my UI stuff (the entire UI is done programmatically, no nibs or storyboards). Here is a bit of the viewDidLoad of MAController:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.navigationController setNavigationBarHidden:YES]; // I commented this line out and realized it does nothing
I go on (in viewDidLoad) to add a bunch of subviews to self.view, like this
[self.view addSubview:self.backgroundImageView];
Earlier, I created a viewController in the AppDelegate class and it was called view, so I assumed it was refereeing to that but now since I've changed it (in AppDelegate) to viewController, I guess I was thinking wrong?
And then finally, I create a UIView in 'viewDidLoad`:
UIView *header = [[UIView alloc] initWithFrame:headerFrame];
header.backgroundColor = [UIColor clearColor];
self.tableView.tableHeaderView = header;
and start adding a bunch of subviews to this new UIView I created header.
So, in short, I have no idea what is happening. Later, when I tried telling (from a method inside MAController) self.navigationController (which I assumed to be navigationController in charge of everything in my project - created at the beginning in the AppDelegate) to pushViewController a new viewController that I was going to use as a detailView for a table, it got weird.
So I'm just trying to understand what has control, and what the rootViewController is, and just what is happening.
The main window root is set to a view controller and not the navigation controller
Change:
self.window.rootViewController = viewController;
to:
self.window.rootViewController = navController;
EDIT:
You can access the navigationController from anywhere by asking your appDelegate. It is normally not considered a good practice:
MAAppDelegate *delegate = (MAAppDelegate *)[[UIApplication sharedApplication] delegate];
UINavigationController *nav = delegate.navigationController;
Don't forget to:
#import "MAAppDelegate.h"
First, take a little time and read through how navigation controllers work. The documentation is really helpful:
https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
Second, your problem is that your window's root view controller is not the navigation controller you created. Rather it is an instance of MAController. This is what you're doing:
UIViewController *viewController = [[MAController alloc] init];
// some other code ...
self.window.rootViewController = viewController;
I think you meant to add MAController as the root view controller of the navigation controller and make the navigation controller your window's root. If so, you'll want to set your view controllers up like this:
UIViewController *viewController = [[MAController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navController;
Another potential problem is that you don't seem to be doing anything with your detailViewController. Maybe that's confusing you too.