I'm having a little trouble with essentially flipping a UIView to imitate a card turning over.
As it stands, I have created two UIViews (front and rear) inside a XIB and loaded it into the storyboard as such:
//Initiate the view from the XIB
CustomClass *drag = [[CustomClass alloc] initWithFrame:rect];
//Add the view to the view (container) within the storyboard
[self.draggableView addSubview:drag];
Inside my custom class is the following:
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
self = [[[NSBundle mainBundle] loadNibNamed:#"Draggable"
owner:self
options:nil] objectAtIndex:0];
return self;
}
This satisfactorily presents the front view...
Now I cannot for the life of me work out how to flip the view to display another UIView inside the same XIB... This UIView is available at "objectAtIndex:1".
I'm pretty certain the code I need includes:
[UIView transitionWithView:UIVIEW
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromBottom
animations: ^{}];
If xib has many views, You should use loadNibNamed to create the view in xib file:
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"BlueView" owner:nil options:nil];
self.blueView = views[0];
self.yellowView = views[1];
I have developed a custom UIView with nib file such that I can reuse it whenever needed. Now the thing is I have a nib of a UIViewController and I am drag and drop a Dummy UIView inside it and changing the Class Name to custom view's class name. This works fine when I run my application. I can see the Custom View in my screen on runtime. But I can not see it in Interface builder. So, my question is, is it possible to see the custom view's layout in view controller's nib through interface builder?
You can't load a nib from inside another nib.
You could get around this by leaving the view in your view controller's nib as a placeholder, then loading the custom view's nib in viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
UINib *customViewNib = [UINib nibWithNibName:#"CustomView" bundle:nil];
CustomView *customView = [[customViewNib instantiateWithOwner:self options:nil] objectAtIndex:0]
customView.frame = self.placeholderView.bounds;
[self.placeholderView addSubView:customView];
}
Hi can I ask if can I mix the xib with my UIViewController in storyboard? Like they share a controller in their files owner because I'm planning to create a expandable view by using nib as the expandedview and I want to pass a value from nib file to the UIViewController in storyboard. Thanks.
I don't recommend you mix xib and view controller from storyboard and hook them all together.
If you want to add a UIView as an extended view to your view controller you can do something like this:
// Load the first view inside our xib from main bundle
UIView *view = [[NSBundle mainBundle] loadNibNamed:#"nib_name" owner:self options:nil][0];
// Define new X,Y to our view
float new_x_position = 0;
float new_y_position = 400;
view.frame = CGRectMake(new_x_position, new_y_position, CGRectGetWidth(view.frame), CGRectGetHeight(view.frame));
// UILabel inside our nib, '111' is the tag we set to our UILabel
UILabel *label = (UILabel*)[view viewWithTag:111];
// Add our view to the current view as a sub view
[self.view addSubview:view];
I hope I understood you correctly.
In storyboard you are not provided with xibs, but if you want to use them to load from nib then use :
MyViewController *viewController = [[MyViewController alloc] initWithNibName:#"CustomDownloadedXib" bundle:nil];
I'm developing an iOS app with latest SDK.
I want to create a custom UIView and set layout using a XIB file.
To this XIB, I have added four UIButtons using Interface Builder.
Now I want to connect these four buttons to my custom UIView class and manage there IBActions. This is very important, I have to do it this way.
To load the xib I do:
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder]))
{
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:#"MyCustomView"
owner:self
options:nil] objectAtIndex:0]];
}
return self;
}
I also have a storyboard and I have added an UIView to main ViewController using Interface Builder.
My question is: What do I have to do to connect the new XIB file to my custom UIView on Interface Builder?
I think I have to open this new xib on Interface Builder and set main ViewController as File's Owner, and set my custom UIView class as class for the view on this new XIB, but I'm not sure.
And, on main ViewController change the class for this new view to my custom UIView.
In Interface Builder, set the custom class to your CustomView.Make the connections to this custom class. In the whichever view controller you want to use this xib, Simply load the nib using loadNibNamed:owner:options: method.
CustomView *cView = [[[NSBundle mainBundle] loadNibNamed:#"CustomView"
owner:nil
options:nil] objectAtIndex:0];
[cView.button1 addTarget:self action:#selector(actnForBtn1:) forControlEvents:UIControlEventTouchUpInside];
[cView.label1 setText:#"sometext"];
[self.view addSubview:cView];
And do add the method actnForBtn1:(id)sender in your view controller to do different things in different view controllers.
In View.h
+(View *)loadViewFromNib;
In View.m
+(View *)loadViewFromNib{
return (View *)[[[NSBundle mainBundle] loadNibNamed:#"View" owner:self options:0] objectAtIndex:0];
}
To load the View call
View *view = [View loadViewFromNib];
In your View.xib file set the Files Owner class to View and your Views class to View connect the Outlets only to the View, not to the FilesOwner!
When working with views and view controllers in an iPhone app, can anyone explain the difference between loadView and viewDidLoad?
My personal context, is that I build all my views from code, I do not and will not use Interface Builder, should that make any difference.
I've found that often when I add init code to loadView, I end up with an infinite stack trace, so I typically do all my child-view building in viewDidLoad...but it's really unclear to me when each gets executed, and what is the more appropriate place to put init code. What would be perfect, is a simple diagram of the initialization calls.
Thanks!
I can guess what might be the problem here, because I've done it:
I've found that often when I add init code to loadView, I end up with an infinite stack trace
Don't read self.view in -loadView. Only set it, don't get it.
The self.view property accessor calls -loadView if the view isn't currently loaded. There's your infinite recursion.
The usual way to build the view programmatically in -loadView, as demonstrated in Apple's pre-Interface-Builder examples, is more like this:
UIView *view = [[UIView alloc] init...];
...
[view addSubview:whatever];
[view addSubview:whatever2];
...
self.view = view;
[view release];
And I don't blame you for not using IB. I've stuck with this method for all of Instapaper and find myself much more comfortable with it than dealing with IB's complexities, interface quirks, and unexpected behind-the-scenes behavior.
loadView is the method in UIViewController that will actually load up the view and assign it to the view property. This is also the location that a subclass of UIViewController would override if you wanted to programatically set up the view property.
viewDidLoad is the method that is called once the view has been loaded. This is called after loadView is called. It is a place where you can override and insert code that does further initial setup of the view once it has been loaded.
viewDidLoad()
is to be used when you load your view from a NIB and want to perform any customization after launch
LoadView()
is to be used when you want to create your view programmatically (without the use of Interface Builder)
Just adding some code examples to demonstrate what NilObject said:
- (void)loadView
{
// create and configure the table view
myTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStyleGrouped];
myTableView.delegate = self;
myTableView.dataSource = self;
myTableView.scrollEnabled = NO;
self.view = myTableView;
self.view.autoresizesSubviews = YES;
}
- (void)viewDidLoad
{
self.title = #"Create group";
// Right menu bar button is to Save
UIBarButtonItem *saveButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Save" style:UIBarButtonItemStyleDone target:self action:#selector(save)];
self.navigationItem.rightBarButtonItem = saveButtonItem;
[saveButtonItem release];
}
To prevent an infinite loop from happening when you read self.view, call the class' super implementation when you load a view. The super implementation will allocate a new UIView for you.
- (void) loadView {
[super loadview];
// init code here...
[self.view addSubView:mySubview1]; //etc..
}
The easiest way to use loadView is to make some type of base view controller, like MyBaseViewController which is subclass of UIViewController. In it's loadView method create view in this way:
-(void) loadView {
if ([self viewFromNib]) {
self.view = [self viewFromNib];
} else {
self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
}
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
self.view.backgroundColor = [UIColor whiteColor];
}
And when you need to make some view controller you just use subclass of MyBaseViewController and in it's loadView controller you just call [super loadView] like this
//sucblass loadView
-(void) loadView {
[super loadView];
//rest of code like this..
UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];
[self.view addSubview:myLabel];
[myLabel release];
}
loadView() is called when your controller is asked to create its self.view. You can do it by yourself like
self.view = [UIView alloc] init...];
Or your controller's parent UIController class has already a method name -loadView() which initializes your self.view into blank view. Then you can call
[super loadView];
I really recommend the second approach as it encourages the inheritance. Only if your view controller is not directly inherited from UIViewController.
The definition given by Apple on viewDidLoad mentioned that it is called after the controller’s view is loaded into memory. To put it in a simple term, it is the first method that will load.
You might be thinking under what condition will this method being fully utilized? The answer is, basically whatever you wanted the app to load first. For instance, you might want a different background color, instead of white, you could perhaps choose blue.