Unable to add additional subview to uiwindow apart from rootviewcontroller - ios

Below is my code from app delegate in didFinishLaunchingWithOptions
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
CGRect windowFrame = self.window.frame;
UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, windowFrame.size.height-100, windowFrame.size.height, windowFrame.size.height)];
bottomView.backgroundColor = [UIColor redColor];
[self.window addSubview:bottomView];
// self.viewController.view.frame = CGRectMake(0, 0, windowFrame.size.width, windowFrame.size.height-100);
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
My ViewController is FreeForm and its height is just around 245. As you can see i am trying to put a bottom view that is 100 points height.
I am just trying to learn this.
But the view always filling the entire screen. If i comment out setting view controller as windows rootviewcontroller i can see my bottomview there on the screen.
What i am doing wrong? Please advice.
Thanks.

Instead of
self.window.rootViewController = self.viewController;
when i code
[self.window addSubview:self.viewController.view];
gave me the expected result and it governs the freeform size.
It appears when set as rootviewcontroller it fills the entire available screen regardless of the freeform size set on the XIB.

write only one sentance
[self.window bringSubviewToFront: bottomView];
OR
Add bottomView to window as ,
[[[[UIApplication sharedApplication] delegate] window] addSubview:bottomView];

I'm not sure why you're trying to do this, but the freeform setting in IB (at least for xib files) seems to be for layout purposes only. It doesn't actually affect the size you get when the view loads. If you want it to be shorter, then set its frame in the viewDidAppear: method in ViewController, not in the app delegate -- the view hasn't been loaded there yet, so it's too early to set the frame.

Related

ViewController loaded in AppDelegate BUT shifted down

Inside AppDelegate.m file I have:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
self.MainVC = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.HamMenuVC = [[HamMenuViewController alloc] initWithNibName:#"HamMenuViewController" bundle:nil];
self.RevealVC = [[SWRevealViewController alloc]initWithRearViewController:self.HamMenuVC frontViewController:self.MainVC];
self.navC = [[UINavigationController alloc]initWithRootViewController:self.RevealVC];
self.window.rootViewController = self.navC;
[self.window makeKeyAndVisible];
Which is supposed to load my Main VC and then the hamburger menu VC (or slider? in iOS talk), and when I start the app I get the loaded VCs BUT the entire view seems to be shifted down roughly 30 pixels and there's this white space above.
As you can see below, this is the top of my screen and the black is where the MainVC starts:
the top of the screen
I've checked the 'self.view.frame.origin.y' inside the MainVC and it says 0.0 AND I've checked the '[[UIScreen mainScreen] bounds].size.height' and it's giving me the correct height for the device I'm running it on AND I checked the '[[UIScreen mainScreen] bounds].origin.y' and it says 0.0.
Does anyone have a clue why all the data is saying it's in the right place but the fact is it's in the wrong place on my physical device AND on any simulator I choose?
It looks like that's the UINavigationBar on top of the screen. In your code, you're setting your rootViewController with a UINavigationController.
self.navC = [[UINavigationController alloc]initWithRootViewController:self.RevealVC];
self.window.rootViewController = self.navC;
If you need to hide the navigation bar, call this method in your RevealVC's viewDidLoad method:
[self.navigationController setNavigationBarHidden:YES animated:YES];
Also, quick tip, try to name your properties starting with lowercase letters.

Resize a UIView to allow space for ad unit

I am trying to add an ad unit above a subclass of UIView RCTRootView. This would move the RCTRootView down about 50px. This is my current attempt.
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:#"test"
launchOptions:launchOptions];
CGRect frame = rootView.frame;
frame.size.height -= 50;
rootView.frame = frame;
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.autoresizesSubviews = YES;
UIViewController *rootViewController = [[UIViewController alloc] init];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
This is a React Native project, so use of a StoryBoard. How can I resize the rootView?
How can I instantiate and append a viewController within UIWindow that is above the rootView (Ad unit)?
You can use container view controller to kind of compose 2 view controllers into one.
Create containerViewController:
UIViewController* containerViewController = [[UIViewController alloc] init];
Create your child view controllers, that you will add to container view controller:
In your case they will be rootViewController and adViewController, in the example I'll call them firstChildViewController and secondChildViewController).
UIViewController* firstChildViewController = [[UIViewController alloc] init];
UIViewController* secondChildViewController = [[UIViewController alloc] init];
Add your child view controllers to container view controller in right order:
If firstChildViewController should be above secondChildViewController, then first add secondChildViewController and then firstChildViewController to create right subviews hierarchy).
Do not forget about layout your child view controller's views (TODO's are set where it is needed).
[containerViewController addChildViewController:firstChildViewController];
[containerViewController.view addSubview:firstChildViewController.view];
// TODO: layout firstChildViewController.view in containerViewController.view here
[firstChildViewController didMoveToParentViewController:containerViewController];
[containerViewController addChildViewController:secondChildViewController];
[containerViewController.view addSubview:secondChildViewController.view];
// TODO: layout secondChildViewController.view in containerViewController.view here
[secondChildViewController didMoveToParentViewController:containerViewController];
To layout container view controller's views trust them as regular UIView's and use preferred method to set their coordinates and sizes (autolayout or manual layout).
To move view down 50px you should, for example, constraint bottom of the top view to top of the bottom view and height of the top view to 50.
There you go, you have two view controllers layed out as you need and all you need to do is to set containerViewController to window's rootViewController:
[window setRootViewController:containerViewController];
Hope it will help.
Try this it may helps, but probably solving this is React is better than changing screen size
UIViewController *rootViewController = [[UIViewController alloc] init];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
rootViewController.view.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-50);
As suggested by mihir mehta storyboard is most convenient way to handle UI in iOS. Here is link from where you can learn to add story board.
Creating a new storyboard in XCode and making it the main one (black screen in simulator)
Also there are ample tutorials on subject.

Adjusting uitableview height

I'm creating a simple application with uitableview. I want to create everything in code. I used following code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
FBVCalendarViewController *calendarViewController = [[FBVCalendarViewController alloc] init];
self.window.rootViewController = calendarViewController;
[self.window makeKeyAndVisible];
return YES;
}
...
- (void)loadView
{
UITableView *calendarItems = [[UITableView alloc] init];
self.view = calendarItems;
}
it works, but application fills the entire phone screen intersecting with standard phone title bar.
What is the right way to adjust view height?
Since UITableView inherits from UIScrollView, you should take care of the changes appeared with IOS 7.
A solution to your problem is:
if ([self respondsToSelector:#selector(setNeedsStatusBarAppearanceUpdate)]) {
[self setNeedsStatusBarAppearanceUpdate];
self.automaticallyAdjustsScrollViewInsets = NO;
}
(this will keep the table view below the status bar).
Hope that helps. But you should probably have a look at changes introduced with IOS 7.
So I solved my problem with the following code in loadView:
- (void)loadView
{
UITableView *calendarItems = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
UIView *rootView = [[UIView alloc] init];
[rootView addSubview:calendarItems];
self.view = rootView;
}
I used empty UIView as a parent for tableView and changed constructor to explicitly specify UITableView frame. I think that better approach would be to use autolayout (currently it just does not work as expected when I rotate device) and position table view to the full screen or implement device rotation callback and update frame there.

UINavigationBar is smaller than it has to be

I'm developing an app and I have a sing-in/sign-out process. When the user clicks in the sign-out button I want the user to be taken to the home screen. To do this I created the following method in the app delegate:
- (void) restartAppWhenLogOut{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
WelcomViewController *welcomeViewController = [[WelcomViewController alloc]init];
self.navController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController];
[self.window setRootViewController:navController];
[self.window makeKeyAndVisible];
}
When the user clicks the "Log out" button I call this:
[[UIApplication sharedApplication].delegate restartAppWhenLogOut];
And it works fine except for one thing. The UINavigationBar is smaller than it should be! Here is an screenshot of how it looks:
There is an small black line that should be filled by the UINavigationBar...
Any idea why this is happening?
=======================================Edit=======================================
I removed the new windows creation as David M. told me to do in one comment but It still fails:
[self.navController popToRootViewControllerAnimated:NO];
WelcomViewController *welcomeViewController = [[WelcomViewController alloc]init];
self.navController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController];
[self.window setRootViewController:navController];
I tried to figure out the error..but didn't find out..so, i suggest you try to setting up the navigation bar manually..
Creating a new window is forbidden: "To change the content your app displays, you can change the window’s root view; you don’t create a new window." UIKit isn't intended to work that way.
Following json advice this is what I did in the viewDidLoadof the view controllor with the UINavigationBar problem:
[self.navigationController.navigationBar setFrame:CGRectMake(0, 20, 320, 44)];
I hope it helps!

setRootViewController: doesn't work as expected after setViewControllers: have been called

I created a view controller programmatically and set it as a root controller. All worked perfect as it was expected:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
CustomViewController *vc = [[CustomViewController alloc] init];
[[self window] setRootViewController:vc];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
Then I added an UITabBarViewController, set its 'viewControllers' property to point to (an array to) the main viewController 'vc'.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
CustomViewController *vc = [[CustomViewController alloc] init];
UITabBarController *tbc = [[UITabBarController alloc] init];
NSArray *controllers = #[vc];
[tbc setViewControllers:controllers];
[[self window] setRootViewController:vc];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
and the view stoped to show at the screen upon launch, also there is warning about the root view controller wasn't set. After adding the string below the view of 'vc' controller is finally loaded, but there is a blank line at the bottom of the screen, as if the UIBarController modified [[UIMainScreen bounds].
[[self window] addSubview:vc.view];
I'm new to iOS development, and I'm a bit confused. It seems I don't understand some very fundamental things about the view controllers hierarchy, but after reading the "View Controller Programming Guide" by Apple, I still don't understand where am I wrong.
The setRootViewController: method should auto assign the _view of argument view controller as default view of the window, but it doesn't happen if the named view controller was already previously pointed by viewControllers property of UITabBarViewController. Though I checked the debugger and found that 'vc' object isn't changed after setViewControllers: method is called.
Could you please explain me what is going on or point me to a documentation I should read?
UPDATE: I'm not going to insert the 'vc' controller into the 'tbc' controller. What I'd like is to display the 'vc' view fullscreen, as it would normally displayed without the code about 'tbc'.
From my point of view, adding another view (tbc in my case) should NOT affect this behaviour.
Of course, that's pretty useless from practical point of view, but I'd like to know what's going on under the hood.
You should set tbc as rootViewController.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
CustomViewController *vc = [[CustomViewController alloc] init];
UITabBarController *tbc = [[UITabBarController alloc] init];
NSArray *controllers = #[vc];
[tbc setViewControllers:controllers];
[[self window] setRootViewController:tbc];
[[self window] addSubview:tbc.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
When you add vc to the tab bar controller, it becomes a child of that controller. The root view controller of the window can't be a child, which is why you get that error. If you want vc to be full screen, then don't put it in the tab bar controller, and then at some point, you switch the window's root view controller to be the tab bar controller (if that's what you want).
You haven't said what you want to use vc for. A better way, depending on its use, might be to present it modally (so it takes the whole screen) from whichever controller is in the first tab of your tab bar controller. Do this from viewDidAppear, and it will be the firsts thing the user sees when the app starts up.

Resources