I'm implementing an application, in which i use several view controllers. But i've found a strange behaviour of my app' when it changes of viewcontroller. Let me explain :
We are in a first viewcontroller, his init method is :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
Menu = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)];
self.view.backgroundColor = [UIColor greenColor];
[self.view addSubview:Menu];
[Menu release];
}
return self;
}
After that, to change of viewcontroller and pass from the first to another, i call this method :
-(void)GoPlay
{
if (!parametresviewcontroller)
{
parametresviewcontroller = [[ParametresViewController alloc]init];
}
UIView *menuView = menuviewcontroller.view;
UIView *paramView = parametresviewcontroller.view;
[menuviewcontroller viewWillAppear:NO];
[parametresviewcontroller viewWillDisappear:NO];
[menuView removeFromSuperview];
[self.view addSubview:paramView];
[menuviewcontroller viewDidAppear:NO];
[parametresviewcontroller viewDidDisappear:NO];
}
So the init method of the second viewcontroller is called, i put it next :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
Parametres = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0)];
Parametres.backgroundColor = [UIColor redColor];
[self.view addSubview:Parametres];
[Parametres release];
}
return self;
}
And the result is :
Why this strange behavior occured ? I really don't understand why the is a gap between the first and the second one...
Thank you ! =)
Ok, The problem is, both the class Is a UIViewController and you have set statusbar for both ViewController's View in XIB file. When you set StatusBar Than the view frame changes its y to 20 pixel below means you have set it to 0 but originally it is 20.
So when you add subView second ViewController's view on the first ViewController's View before doing this set:
secondViewController.view.frame = firstViewController.view.bounds;
. This will solve your problem.
First of all, DO NOT CALL viewWillAppear, viewWillDisappear, viewDidAppear and viewDidDisappear by yourself, this methods are called by the OS in some specific points of a UIViewController life-cycle.
Second, initWithNibName is not the proper method for adding subviews to the controller's view, for that you should use viewWillAppear, viewDidAppear or viewDidLoad.
Third, what you are doing is not changing of view controllers is simply adding a view controller's view to another view controller view, for changing UIViewController you should use addChildViewController: and removeFromParentViewController methods or use UINavigationController
I've found a solution : iPhone hiding StatusBar shifts view down by 20 pix
Use
[self setWantsFullScreenLayout:YES];
in the init method in my case.
Thank you all !
Related
I have a view controller called "Help". I placed a label on the view controller story board, but in simulation I couldn't see the label. I used REMenu to put a menu at the top of the view. I can see the menu bar, but I cannot see the label. Here are the files.
#import "Help.h"
#interface Help ()
#end
#implementation Help
#synthesize helpText1;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor whiteColor]];
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleBack:)];
helpText1.text=#"Hiii";
helpText1.hidden=NO;
// Do any additional setup after loading the view.
}
-(void)handleBack:(id)otherView{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *myVC = (Controller *)[storyboard instantiateViewControllerWithIdentifier:#"QRList"];
[self.navigationController pushViewController:myVC animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Here is the code that calls the "Help" view controller.When we click on the help option in the menu, it will call the "help" view controller.
REMenuItem *helpItem = [[REMenuItem alloc] initWithTitle:#"Help"
subtitle:nil
image:[UIImage imageNamed:#"Ic"]
highlightedImage:nil
action:^(REMenuItem *item) {
NSLog(#"Item: %#", item);
Help *controller = [[Help alloc] init];
[weakSelf setViewControllers:#[controller] animated:NO];
}];
The "Help" view controller is getting called but I couldn't see the label which I dragged on storyboard. I couldn't figure out the issue.
I guess, that your label is being at a wrong view. Probably, your pushed controller doesn't contain the label you put in your nib file. Try to add other objects and see what's happening. If the problem is that I just guessed, then find the exact controller, choose a view and put there the label. Hope you solve that!
Use debug, put breakpoints, to see where you lose label. Check your layouts, maybe...tie your lable to top Space to superView, leading or tralling space to supeView or bottom space to superView. And beginning Xcode 4.4 we don't need synthesize, each added default
I'm appending code to an existing app to add a modal loginView, the old project does not use xib, and the new view controller does.
The present project load its rootViewController this way
- (void) loadView
{
// this should take up the entire screen...
UIView * view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
view.backgroundColor = [UIColor blueColor];
self.view = view;
sideBar =
[[SideBarView alloc] init];
sideBar.rootViewController = self;
[self.view addSubview:sideBar];
pageView =
[[PageView alloc] initWithTitle:DataEntryTitle
client:client];
pageView.rootViewController = self;
//I added this to instantiate the new view controller
_aLoginView = [[LoginViewController alloc]initWithUser:aUser];
[self.view addSubview:pageView];
}
To launch the modal view controller I'm using this code.
-(void)viewDidAppear:(BOOL)animated{
_aLoginView.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:_aLoginView animated:YES completion:nil];
}
As long as I understand the reason for the modal LoginView appearing blank is that I'm creating a new instance of it, instead of calling the existing xib definition. Does someone know what should I do to reference the xib? The old project does not use storyboard, nor xib files.
Thanks,
With your info I think I'm doing something wrong in LoginViewController.m, but I don't know exactly what.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (id)initWithUser:(verifyUser *)aUser
{
self = [super initWithNibName:#"LoginViewController" bundle:[NSBundle mainBundle]];
if (self) {
// Custom initialization
_UserModel = aUser;
}
return self;
}
You want to create the view controller by loading it from the nib
[[LoginViewController alloc] initWithNib:#"nib file name" bundle:[NSBundle mainBundle]]];
If you want to keep your initWithUser: initializer you should be able to do
self = [super initWithNib:#"nib file name" bundle:[NSBundle mainBundle]];
The files owner of your xib is not set.
Open your xib and select the file owner option in the top left
Then on the right pane set the files owner to your view controller:
FOOTNOTE
As an aside, you don't need to set the frame of your view controller in viewDidLoad. It isn't a ViewControllers responsibility to evaluate its own size. A view controller is merely responsible for maintaining the relationship between the model and the view. It is the responsibility of the container or parent ViewController to set the size.
Happy coding
I am trying to fix someone's code and am running into a problem. Here is the situation:
I have a full screen UIViewController that has a bottom bar button. When I press that button, it shows a popup view controller in the bottom left of the screen. That view controller inside the popup also has a button, and when I press THAT button it pushes a new view controller into my popup window. That new view controller is a UITableView that can have some large number of elements. The problem is that when I try to scroll down to see some offscreen elements, the scroll bounces back to the first position in the table, i.e. it does not really scroll.
More specifically here is some code:
In FullScreenVC.h:
#property (nonatomic, retain) NSMutableArray* stuffInList;
#property (nonatomic, retain) UIPopoverController *namePopover;
#property (nonatomic, retain) UINavigationController *nameNav;
#property (nonatomic, retain) UIBarButtonItem* addButton;
Inside FullScreenVC buttonPressed (called when addButton is pressed):
FirstPopupVC *vc=[FirstPopupVC alloc] initWithNibName#"FirstPopupVC" bundle:nil];
vc.delegate=self;
vc.stuffInList=self.stuffInList; // This is just the NSArray of list items
self.nameNav = [[[UINavigationController alloc] initWithRootViewController:vc] autorelease];
self.namePopover = [[[UIPopoverController alloc]
initWithContentViewController:self.nameNav] autorelease];
[vc release];
[self.namePopover presentPopoverFromBarButtonItem:self.addButton
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
In other words, the FirstPopupVC object vc is the root view controller of a UINavigationViewController nameNav, and nameNav is the navigationcontroller that is the content inside the namePopover UIPopoverController. I think the last line launches FirstPopupVC as a popup from the addButton. Note also that the XIB file FirstPopupVC.xib is a simple NIB file that has a few simple views (label etc) and a little button that a user can press to get the second popup, as we'll see.
Inside FirstPopupVC we have:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// some other irrelevant initialization stuff here ...
self.contentSizeForViewInPopover = CGSizeMake(320, 340);
}
return self;
}
-(void)littleButtonClicked:(id)sender {
SecondPopupVC * secondVC=[[SecondPopupVC alloc]
initWithNibName:"#SimpleTableView" bundle"nil];
secondVC.delegate=self;
secondVC.stuffInList=self.stuffInList;
[self.navigationController pushViewController:secondVC animated:YES];
[secondVC release];
}
This of course presents the second view controller inside the popop.
Inside SecondPopupVC we have:
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.contentSizeForViewInPopover = CGSizeMake(320, 340);
}
return self;
}
Apparently the contentSizeForViewInPopover call here will set the size of the popover view with the table view. It looks like this is called inside initWithNibName in both the first and second view controllers.
So again, the problem is that if my listOfStuff is large, ie if the set of items in the table is large, then the table will not stay scrolled beyond the first visible set of rows. I can scroll down to see these items but as soon as I release the mouse pointer (on the emulator) or my finger (on the device), it bounces back to the top of the list.
I tried to add autoresizingmak code as discussed in table view in popover is not scrolling but that didn't work for me.
So how can I fix the above code so that my table stays scrolled when I try to scroll it?
Well, it appears that the problem has something to do with the fact that secondVC is created from a NIB file rather than programmatically. I tried doing this instead:
-(void)littleButtonClicked:(id)sender {
SecondPopupVC * secondVC=[[SecondPopupVC alloc] init];
CGSize contentSize = CGSizeMake(320, 320);
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,
contentSize.width, contentSize.height)];
popoverView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight);
UITableView *tblView = [[UITableView alloc]initWithFrame:popoverView.bounds];
tblView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight);
tblView.delegate = secondVC;
tblView.dataSource = secondVC;
tblView.rowHeight = 44;
[popoverView addSubview:tblView];
secondVC.view = popoverView;
secondVC.contentSizeForViewInPopover = contentSize;
secondVC.stuffInList=self.stuffInList;
[self.navigationController pushViewController:secondVC animated:YES];
[secondVC release];
}
and guess what? It works fine. So why would there be such a problem when SecondPopupVC is initialized from a NIB file rather than using code?
I have a UINavigationController class, I want to add on a button with the method addSubview but its not working
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
UIButton *testbtn = [[UIButton alloc] initWithFrame:CGRectMake(20, 90,28,20)];
[self.view addSubview:testbtn];
}
return self;
}
I assume because you're trying to do this on a navigation controller, you want a bar button item on the toolbar. You need to do this in the UIViewController, not the UINavigationController:
UIBarButtonItem * doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonSystemItemDone
target:self
action:#selector(buttonPressed:)];
[self.navigationItem setRightBarButtonItem:doneButton];
Also, you should grab a cup of coffee and read through the "overview" section of the UINavigationController class reference. It'll take about 10 minutes and you'll be happy you did.
If I'm wrong, and you do want a UIButton (not a UIBarButtonItem), you also need to do that in a UIViewController subclass. Also, you should use its factory method, not a typical alloc/init:
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(20, 90,28,20)
I don't believe you can add a button to a UINavigationController - it doesn't actually have a view of its own. The UINavigationController is more of a behind-the-scenes organizer for holding and displaying other UIViewControllers.
You'll need to take your [self.view addSubview:testbtn] and put that in the code of a UIViewController, instead of in the code for the UINavigationViewController. And as David Doyle pointed out in his answer, it's considered better practice to put something like that in viewDidLoad rather than in initWithNibName.
If you want to modify a View Controller's view, its not a good idea to do so in the init method. The nib file that extracts the resources that create the View Controller's view takes a small amount of time to complete.
You're better off modifying the View Controller's view by overriding the method -[UIViewController viewDidLoad] like so:
- (void)viewDidLoad
{
UIButton *testbtn = [[UIButton alloc] initWithFrame:CGRectMake(20, 90,28,20)];
[self.view addSubview:testbtn];
}
I am making an app in which I created custom navigation bar - MyNavigationBar (extends UIView):
MyNavigationBar.xib :
MyNavigationBar.m :
+(id)navigationBar{
MyNavigationBar * bar = (MyNavigationBar *) [[[NSBundle mainBundle] loadNibNamed:#"MyNavigationBar" owner:self options:nil] objectAtIndex:0];
return bar;
}
Then in NavigationViewController implementation I use this code to add view showed above to navigationBar:
NavigationViewController.m:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
_navBar = [MyNavigationBar navigationBar];
[self.navigationBar addSubview:_navBar];
}
return self;
}
When the left button (subview of MyNavigationBar) is pressed
[[self navigationController] popViewControllerAnimated:YES];
is called.
And the problem is that on that pop animation glitch happens, it looks like this:
Back button become visible for all animation duration and then disappears.
I have tried this but nothing happens:
[_navigationBar.backItem setHidesBackButton:YES];
Instead of adding custom subview to navigation bar try setting navigationItem.titleView to your custom UIView or use [UINavigationBar appearance] and [UIBarButtonItem appearance] APIs to customize standard controls.