I am trying to create a custom UIView and have it load in a xib file. The custom UIView is called JtView and here is the code:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
NSLog(#"initWithFrame was called"); // this was called
if (self) {
// Initialization code
[[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:NULL];
[self addSubview:self.view];
}
return self;
}
-(void)awakeFromNib
{
[super awakeFromNib];
[self addSubview:self.view];
}
In creating the xib file (File -> New -> File -> User Interface -> View), I deleted out the main Window and dragged a View from Xcode's object pallette. I tried alt-dragging to the header for JtView but this wasn't working. Do I need to create an association here or should I just leave what XCode created in place? (edit - see comments below for further clarification)
I have also added a UILabel to the xib.
However, when I run in simulator and set the background color to red, the label is not showing up. Do I need to create the UILabel as a reference in the custom UIView? Should I be deleting this or leaving it in place?
thx
edit 1
Here's a screenshot of the connections and the header file:
I solve it adding a class method to the UIView:
+ (id)customView;
+ (id)customView
{
CustomView *customView = [[[NSBundle mainBundle] loadNibNamed:#"CustomView" owner:nil options:nil] lastObject];
// make sure customView is not nil or the wrong class!
if ([customView isKindOfClass:[CustomView class]])
return customView;
else
return nil;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CustomView *customView = [CustomView customView];
//And where you gonna use it add this line:
//this self.view refers to any view (scrollView, cellView...)
[self.view addSubview:customView];
}
I hope it´s gonna help
Try this:
-(void)awakeFromNib {
NSArray *obj = [[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil];
[self addSubview:obj[0]];
}
Or if you have an #property IBOutlet named "nibview" you could do:
-(void)awakeFromNib {
[[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil];
[self addSubview:self.nibview];
}
Related
I have a custom UIView which I am loading in this manner
- (id)initWithFrame:(CGRect)frame withDelegate:(id)del
{
self = [super initWithFrame:frame];
UIView *myView;
if (self)
{
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class])
owner:self
options:nil];
for (id object in nibViews)
{
if ([object isKindOfClass:[self class]])
myView = object;
}
myView.frame = frame;
myView.backgroundColor = [UIColor clearColor];
[self addSubview: myView];
}
self.delegate = del;
return self;
}
On loading the view like this when UIView method returns self all the outlets linked in the Interface Builder are nil. Is it not the right way ?
Use this method for load particular xib from bundle
UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
Try this :
self = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class])
owner:self
options:nil] objectAtIndex:0];
Use this
myView =[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil].firstObject];
Or simple you can use
myView = [nibViews firstObject]
As I understand you provide IBOutlet in the xid and when you try to load the view like you provide these values is nil. This is anticipated becouse you create onew viwe and add the view from xib as subview. So the parrent view does not set this values.
to fixe this you need to rework method as loaded your view.
Please try use this:
+ (id)createWithFrame:(CGRect)frame withDelegate:(id)del
{
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class])
owner:nil
options:nil];
<Provide class name> *myView = nibViews[0];
myView.frame = frame;
myView.backgroundColor = [UIColor clearColor];
myView.delegate = del;
return myView;
}
I have a custom re-usable XIB that I've created and assigned it a class subclasses from UIView.
BannerView.xib (file owner set appropriately
BannerView.h : UIView
BannerView.m
Here is the initWithFrame:
-(instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self) {
self = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] firstObject];
}
return self;
}
Everything works fine and I am able to init this custom .xib and add this to my VC:
BannerView *bannerView = [[BannerView alloc]init];
[_profileContentArea addSubview:bannerView];
Although, I would like this custom .xib to have it's own VC and then be able to add as a subview via the VC instead of the above. How would I go about this considering my existing setup at the moment.
your init method is initWithFrame,so you must created BannerView like
BannerView *bannerView = [[BannerView alloc]initWithFrame:frame];
then you can add to ViewController
-(instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self) {
self = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] firstObject];
}
return self;
}
Please notice the initialize steps
+alloc: alloc memory
-init : initialize necessary properties
You've already get the view object when you call alloc and set some properties in init or initWithFrame:
and when you call
self = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] firstObject];
The old view object is gone because you've just set a new one which is from xib
why don't you use -[UIViewController initWithNibName:nibBundle:] you can set nib whatever you want
Anyone have any idea why when I use this block of code, it doesn't scale the view to the size of the screen. It looks like it loads the xib file as is and doesn't fit it to the width of the device.
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ReceiptView" owner:self options:NULL];
self = (ReciptView *)[nib objectAtIndex:0];
}
return self;
}
And this is the implementation in the controller:
-(void) bookNowAction
{
ReciptView *v = [[ReciptView alloc] initWithFrame:self.view.frame];
[self.view addSubview:v];
}
You are reassigning self in the if block, after you called super initWithFrame. You are essentially wiping out the effect of that call.
I am trying to subclass a UIView using the nib. Using the following code:
- (void)awakeFromNib
{
[super awakeFromNib];
NSArray *v = [[NSBundle mainBundle] loadNibNamed:#"Qus_Scale1to7View" owner:self options:nil];
[self addSubview:[v objectAtIndex:0]];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
NSArray *v = [[NSBundle mainBundle] loadNibNamed:#"Qus_Scale1to7View" owner:self options:nil];
[self addSubview:[v objectAtIndex:0]];
}
return self;
}
this creates the object correctly and view also displayed and when the object loads from its nib the delegate instantly becomes null and ignores any attempt to assign values to it.
Can anyone know the reason why it is?
Thanks in advance.
It won't work reusing same xib for multiple view controllers. If you want to reuse that view make a class that inherits from UIView and add the code there.
#import "SomeProtocol.h"
#interface MyCustomView : UIView {
IBOutlet UIView *headerView;
IBOutlet UIView *footerView;
IBOutlet UIButton *updateBtn;
}
#property (nonatomic, assign) id<SomeProtocol> delegate;
#end
............
#implementation BCFirmwareView
#synthesize delegate = _delegate;
+ (id)viewFromNibWithName: (NSString*)name {
UIView *view = nil;
NSArray *views = [[NSBundle mainBundle] loadNibNamed: name owner: self options: nil];
if (views) {
for (UIView *aView in views) {
if ([aView isKindOfClass: NSClassFromString(name)])
view = aView;
}
}
return view;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder: aDecoder];
if (self) {
}
return self;
}
- (id)init {
self = [[MyCustomView viewFromNibWithName: #"MyCustomView"] retain];
if (self) {
}
return self;
}
- (void)dealloc {
self.delegate = nil;
[headerView release];
[footerView release];
[updateBtn release];
[super dealloc];
}
- (void)awakeFromNib {
[super awakeFromNib];
// Do any additional setup after loading the view from its nib.
headerView.backgroundColor = [UIColor redColor];
footerView.backgroundColor = [UIColor greenColor];
}
- (void)willMoveToSuperview:(UIView *)newSuperview {
[super willMoveToSuperview: newSuperview];
if (!newSuperview)
return;
}
- (void)didMoveToSuperview {
[super didMoveToSuperview];
}
- (IBAction)updateBtnPressed: (id)sender {
// do some stuff
}
#end
The next step is to open the xib in Interface Builder and set your class as the custom class for the view, not for the File's Responder. Right click on the view and make the outlet and actions connections.
Now you should be able to simply make instances of your MyCustomView in any view controller and use it. Will work from Interface Builder as well if you don't forget to change your view custom class to your class.
You can create a custom UIView with Xib and add properties to it.
Then you link the class with the xib and link the properties with the IB.
Or you can only use the
NSArray *v = [[NSBundle mainBundle] loadNibNamed:#"Qus_Scale1to7View" owner:self options:nil];
UIView *view = [v objectAtIndex:0];
and set your objects values using viewWithTag: method.
UILabel *label = (UILabel *)[view viewWithTag:yourTag];
Let me know if this helps.
I create CustomView:UIView with CustomView.xib file.
Now I want to use it by drag view into another XIB (ex: UIViewController.xib) and choose class: customView.
I can load successful when I init CustomView and addSubView to anotherView:
- (void)viewDidLoad{
//Success load NIB
CustomView *aView = [[CustomView alloc] initWithFrame:CGRectMake(40, 250, 100, 100)];
[self.view addSubview:aView];
}
//CustomView.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"INIT");
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
[[nib objectAtIndex:0] setFrame:frame];
self = [nib objectAtIndex:0];
}
return self;
}
In the case reuse CustomCell by drawing it into another XIB and then specify class as CustomView. I know awakeFromNib is called but don't know how to load CustomView.xib.
how to do that?
*EDIT:
initWithCoder is also called when specify class but it create a loop and crash with loadNibNamed. Why that?
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super initWithCoder:aDecoder]) {
NSLog(#"Coder");
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"QSKey" owner:nil options:nil];
[[nib objectAtIndex:0] setFrame:self.bounds];
self = [nib objectAtIndex:0];
}
return self;
}
Directly drag custom xib in your view controller is not possible.But you can do one thing,drag its super class view and set its class to your custom class.And connect its properties to the objects you will place according to your Custom Class.
You can directly load your custom xib using following code:
//load xib using code ....
QSKey *keyView=[[QSKey alloc] init];
NSArray *topObjects=[[NSBundle mainBundle] loadNibNamed:#"QSKey" owner:self options:nil];
for (id view in topObjects) {
if ([view isKindOfClass:[QSKey class]]) {
keyView=(QSKey*)view;
}
}
keyView.label.text=#"CView";
[keyView setFrame:CGRectMake(0, 0, 100, 100)];
[keyView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:keyView];
here label is UILabel object you have used in your custom class as its property.
//Load custom View using drag down objects of type Custom Class Super class.
for (QSKey *aView in self.view.subviews) {
if ([aView isKindOfClass:[QSKey class]]) {
[self addGestureRecognizersToPiece:aView];
aView.label.text=#"whatever!";
}
}
Here label is object of UILabel you have to place on your dragged View to view controller's xib view.Change that view's class to your Custom Class.Then it will will show its label property in outlet connect it to your UILabel object placed over dragged view.
Here is a working code TestTouchonView
And the Screenshot will display as follows.