Objective C: Part of UITableView hidden by Tab bar controller - objective-c

Hi I have a Uitableview added to a Uiviewcontroller as seen in the code below. The controller is part of a UITabbarcontroller.
The problem here is that the tab bar (at bottom of screen) overlaps with the table view. Is there any way to shorten the table height so that it is not partially hidden by the tab bar?
- (void)viewDidLoad
{
[super viewDidLoad];
self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame] autorelease];
self.feedTableView = [[UITableView alloc]init];
self.feedTableView.frame = self.view.bounds;
self.feedTableView.delegate = self;
self.feedTableView.dataSource = self;
[self.view addSubview: self.feedTableView];
[self getData];
[self.feedTableView reloadData];
}

You have two problems here:
You set self.view in viewDidLoad (it should already have been set in loadView).
You set the view frame to applicationframe, but your view does not take up the whole applicationframe (the tab bar controller's view probably does that).
When you have a tabbarcontroller and set viewcontrollers inside it, the tabbarcontroller sets up all the viewcontrollers (tells them when to load and what size to have and when to show). You should never need to set the view's frames in this case. So removing that first line after [super viewDidLoad]; should fix your problem.

Related

Objective c stop animations of UIImageView on UINavigationController segue

I have some strange animations when transitioning between views with UINavigationController. The images start with different frame properties and animate to the ones that i have set each time i segue with UINavigationController. I can't find anything to make that animation go away. Does it have something to do with ViewWillAppear implementation?
- (void)viewDidLoad
{
LoadingView* loadingView;
// adding a loading view
loadingView = [self setViewLoading];
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:#"≡"
style:UIBarButtonSystemItemDone
target:self.revealViewController
action:#selector(rightRevealToggle:)];
// pan gesture for side menu (Facebook style)
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
self.navigationItem.title = #"Brands";
[self.navigationController setNavigationBarHidden:NO];
self.menusDataArray = self.menusData[TAG_MENUS];
// removing loading view.
[self setViewNotLoading:loadingView];
}
- (void)viewWillAppear:(BOOL)animated
{
// if I don't do this, the swipe gesture for the Facebook stile side menu won't be recognised after pressing back on navigation controller bar
[super viewWillAppear:animated];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}

Presenting a modal view controller with cross-disolve isn't showing views added in code

When I present a modal view controller over my view storyboard originated root view controller it flashes the story board view, even if it has been altered. My root view controller has a bright green back ground with large white subview across the top that contains a label bound to an IBOutlet. In UIViewController viewDidLoad I am adding a light gray, slightly transparent UIView that covers the entire view as a subview of the viewcontroller's view. I am also setting the label text to be different than that of the Storyboard layout.
When I trigger the modal, either via segue or via presentViewController:completion: what I see is the light gray view over my label then the view added in code seems to become transparent and animate away and the bright green of the storyboard layout shows up and then the modal view cross-dissolves in. When I dismiss the first and present the second in the completion block i see a cross-dissolve to bright green, pop of light as the added view becomes visible again, pop to bright green and the cross-dissolve in of the second view controller's view.
When I dismiss the second view controller then I see cross-dissolve out to the bright green and then the added light gray, semi-transparent view pops back to being visible.
Anyone have any idea how to stop the cross-dissolve from showing the views underneath the view added in code?
This example is made more jarring if you remove the opacity from the overlay view added in viewDidLoad.
https://github.com/jonnolen/ios-cross-disolve-problem
Code snippet and story board layout:
#interface DTViewController (){
BOOL hasShownSegue;
}
#end
#implementation DTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIView * view = [UIView new];
view.frame = self.view.bounds;
view.backgroundColor = [UIColor colorWithWhite:.95 alpha:.7];
NSLog(#"View Bounds: %#", NSStringFromCGRect(self.view.bounds));
[self.view addSubview:view];
self.label.text = #"Hello!";
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
if (!hasShownSegue){
[self performSegueWithIdentifier:#"modal.1.segue" sender:self];
hasShownSegue = YES;
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
DTCallbackViewController *vc = segue.destinationViewController;
vc.completionCallback = ^{
[self dismissViewControllerAnimated:YES completion:^{
DTCallbackViewController * vc = [self.storyboard instantiateViewControllerWithIdentifier:#"vc.2"];
vc.completionCallback = ^{
[self dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:vc animated:YES completion:nil];
}];
};
}
Figured it out, I don't really like it but it works:
I put all of the maskable content into a separate view:
And then hide that view when I need it to be "masked".
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"View Bounds: %#", NSStringFromCGRect(self.view.bounds));
self.label.text = #"Hello!";
self.content.hidden = YES;
}
Then animations behave as expected. However, this only works with an opaque mask (which is what I needed).

How to setup view in UIViewController

I've created an almost-empty UIViewController class named MyViewController. In the viewDidLoad I'm setting the title and adding a close-button to the navigationItem.leftBarButtonItem.
I'm presenting my MyViewController like this:
MyViewController *myViewController = [[MyViewController alloc] init];
UINavigationController *nc = [[UINavigationController alloc] myViewController];
nc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:nc animated:YES];
When the viewController is presented, the background of it's view is just black. How can I setup it's view to fill-out the screen with an empty view -- just like when the UIViewController is setup in a Storyboard?
I've tried adding the following to the viewDidLoad, but the view is still black:
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
By default a VC's view gets created in -loadView which you usually neither call, nor override. It gets called automatically the first time you request the the VC's view property.
The view's size is automatically set to the 'empty space', like everything except for the status bar without a NavigationController, minus the navbar when using one etc. You shouldn't worry about its size - usually it's just fine.
You can add your own views in -viewDidLoad and remove them again (for low-memory reasons) in -viewDidUnload.
You can add an UIImageView with custom image and then sent it to back
So in your viewcontrollers viewDidLoad
UIImageView *back = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"MyBG"]];
[self.view addSubview:back];
[self.view sendSubViewToBack:back];
If you are using a XIB file you should init the view controller through the method initWithNibName: bundle:

UITableView partially hidden by UITabBar

I've got a UITabBarController which contains a UINavigationController. Within the visible UIViewController, I'm creating a UITableView programatically as follows:
self.voucherTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
self.voucherTableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
However, the UITabBar is overlapping the UITableView.
When I output the height of the [[UIScreen mainScreen] applicationFrame], it returns 460.00 whereas it should be 367.00.
In Interface Builder, I'm using the 'Simulated Metrics' which automatically sets the height of the view to 367.00.
Is there something I'm missing, no matter what I try I can't see to get the 367.00 height that I need.
As a temp fix, I've set the frame of the UITableView manually, this isn't really ideal so it would be nice to work out why this isn't working:
self.voucherTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 367) style:UITableViewStylePlain];
You should use self.view.bounds rather than [[UIScreen mainScreen] applicationFrame] as the last one returns you the whole screen frame while self.view.bounds provides you with your view bounds wich seems what you are searching for.
You should add the UINavigationController instance to the UITabBarController and then add a table view controller to the rootViewController property of the UINavigationController instance which should make your life a lot easier.
As a simple example of this, create an empty window-based application (the templates make this a lot more confusing than it really is).
Add your UIViewController/UITableViewController subclasses to the project then use this code as a guide to setting up your project. This code is in your AppDelegate class:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// create our table view controller that will display our store list
StoresViewController *storeListController = [[StoresViewController alloc] init];
// create the navigation controller that will hold our store list and detail view controllers and set the store list as the root view controller
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:storeListController];
[navController.tabBarItem setTitle:#"TableView"];
[navController.tabBarItem setImage:[UIImage imageNamed:#"cart.png"]];
// create our browser view controller
BrowserViewController *webBrowserController = [[BrowserViewController alloc] init];
[webBrowserController.tabBarItem setTitle:#"WebView"];
[webBrowserController.tabBarItem setImage:[UIImage imageNamed:#"web.png"]];
// add our view controllers to an array, which will retain them
NSArray *viewControllers = [NSArray arrayWithObjects:navController, webBrowserController, nil];
// release these since they are now retained
[navController release];
[storeListController release];
[webBrowserController release];
// add our array of controllers to the tab bar controller
UITabBarController *tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:viewControllers];
// set the tab bar controller as our root view controller
[self.window setRootViewController:tabBarController];
// we can release this now since the window is retaining it
[tabBarController release];
[self.window makeKeyAndVisible];
return YES;
}
In the code sample above the BrowserViewController is a subclass of UIViewController and the StoresViewController class is a subclass of UITableViewController. The UITabBarController and UINavigationController instances are created programmatically and added to the window.
By subclassing the UITableViewController class you avoid having to create a UITableView instance programmatically and get most everything you need out of the box.
When you need to push a detail view onto the UINavigationController instance's stack, you just have use something similar to this:
[self.navigationController pushViewController:YourDetailViewControllerInstance animated:YES];
This will add the detail view UIViewController subclass to the UINavigationController instance's view hierarchy for you and animate the transition.
Lots of controllers in this, but it's totally worth it and will avoid a lot of the problems you're experiencing as this method allows the views to manage resizing and take toolbars/navigation bars into account all by themselves.

UIView transition and animation

I understand modal views cover the entire screen. But I really want a view that covers only half the screen just like the keyboard. So, please tell me why this doesn't work
MyController *controller = [[MyController alloc] initWithNibName:#"MyView" bundle:nil];
CGRect frame = CGRectMake(0,44,768,264);
[controller view].frame = frame;
contoller.delegate = self;
[[self view] addSubView:[controller view]];
[controller release];
I am trying to add a sub view to my current view and make it appear where the keyboard appears.
It throws a BAD ACCESS exception
In my code (above), I was using a custom UIViewController with it's own view [set to UIView on IB]. I couldn't get it to work by setting frame for the view controller's view.
So I added a custom UIView without a Nib file with all the controls (buttons, textfields) added on initWithFrame.
MyCustomView = [[MyCustomView] alloc] initWithFrame:frame delegate:self];
[self.view addSubView:MyCustomView];
Thanks for your comment, Jacob.