I created a UIView subclass associated with .xib file. This UIView subclass is to be used in a UIViewController. In the controller, I think there are two options how we instantiate the UIView subclass:
MyUIView *myView=[[MyUIView alloc] initWithFrame:aRect];
and
MyUIView *myView = [[[NSBundle mainBundle] loadNibNamed:#"MyUIView"
owner:self
options:nil] lastObject];
I prefer the first approach or its variants that allow me to perform custom initialization. The only problem is that I have to specify a frame's rect, which was already specified in .xib (I mean frame's height and width of MyUIView). Yes, I can hardcode it again in aRect, but this is tedious to maintain (e.g., when I change position of UIs in .xib, I have to update aRect, too).
So the second approach should come into mind as the frame rect is automatically set. The remaining problem is I cannot customize the initializer (say, I want to pass extra parameters during initialization).
What's your preference? Which one is better in your opinion?
EDIT1:
Inspired by sergio's answer, I came out with this workaround:
// In MyViewController.m
MyUIView *myView=[[MyUIView alloc] initWithFrame:CGRectMake(x, y, 0.0, 0.0)];
// In MyView.m
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self = [[[NSBundle mainBundle] loadNibNamed:#"UnmovableTagView"
owner:self
options:nil] lastObject];
[self setFrame:CGRectMake(frame.origin.x,
frame.origin.y,
[self frame].size.width,
[self frame].size.height)];
// frame's width and height already determined after
// loadNibNamed was called
...
}
return self;
}
Have you tried using:
MyUIView *myView=[[MyUIView alloc] initWithFrame:CGRectZero];
I don't know if it works in your case (loading the view from a nib), but I use it successfully when I create my custom view programmatically.
You can give it a try.
EDIT:
you could define your own init method for your view:
-(id)initWithPosition:(CGPoint)pos;
and then call:
-(id)initWithPosition:(CGPoint)pos {
if (self = [super initWithFrame:{pos,{0,0}}]) {
self = [[[NSBundle mainBundle] loadNibNamed:#"UnmovableTagView"
owner:self
options:nil] lastObject];
[self setFrame:CGRectMake(frame.origin.x,
frame.origin.y,
[self frame].size.width,
[self frame].size.height)];
// frame's width and height already determined
// after loadNibNamed was called
}
Related
I have an autolayout xib with constraints added in my application.
Then I add my xib view to a scrollView lateral like a pageController.
But when I add this to the scrollView I get a lot of error with constraints and the outlets isn't showed properly. "[LayoutConstraints] Unable to simultaneously satisfy constraints."
This is my xib class code:
#implementation InvitView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
nibname=#"Invit";
[self addSubview:
[[[NSBundle mainBundle] loadNibNamed:nibname owner:self options:nil] objectAtIndex:0]];
}
return self;
}
#end
And I add my xib to the scrollView with this code:
- (void)viewDidLoad {
[super viewDidLoad];
float width = self.scroll.frame.size.width;
float height = self.scroll.frame.size.height;
int count = 0;
InvitView *myView = [[InvitView alloc] initWithFrame:CGRectMake(self.scroll.frame.origin.x, self.scroll.frame.origin.y, self.scroll.frame.size.width, self.scroll.frame.size.height)];
[myView setFrame:CGRectMake(width*count++, 0, width, height)];
[myView setNeedsUpdateConstraints];
[self.scroll addSubview:myView];
}
I'm trying set translatesAutoresizingMaskIntoConstraints = NO; but with this code I lost all constraints, and I want keep this then add to the scrollView.
How can I keep my initial constraints in the xib?
EDIT
On the one hand, I have this constraints to my UIScrollView in my viewwController:
On the another hand I have this in my xib:
And the exactly log is:
I have a xib with constraints, and I have a viewController in my autolayout storyboard with a scrollView where I added the xib.
My xib have constraints, but when I add the xib to the autolayout storyboard the outlets change position and size, it is losing his constraints...
I use this function to create the xib :
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
nibname=#"myViewXib";
[self addSubview:
[[[NSBundle mainBundle] loadNibNamed:#"myViewXib" owner:self options:nil] objectAtIndex:0]];
[self setNeedsLayout];
}
return self;
}
And this is the function to load the xib into my storyboard in the viewDidLoad:
MyViewXib *myView = [[MyViewXib alloc] initWithFrame:CGRectMake(self.scroll.frame.origin.x, self.scroll.frame.origin.y, self.scroll.frame.size.width, self.scroll.frame.size.height)];
[myView setFrame:CGRectMake(width*count++, 0, width, height)];
[self.scroll addSubview:myView];
[self.scroll layoutSubviews];
What is wrong in my code? Why are the constraints not working?
thanks!
Instead of putting add subview code in the viewDidLoad method you can try it by putting it in viewDidAppear method since the view controller don't have the exact frame of any view in viewDidLoad method.
I have a tableview with 2 rows. In the first row I have an UIView and I'm gonna add a custom view on it. I made the custom view as a XIB and I'm adding it like following,
Layout6View *lookLayout6 = [[Layout6View alloc] initWithFrame:CGRectMake(0, 0,cell.mainView.frame.size.width, cell.mainView.frame.size.height)];
[cell.mainView addSubview:lookLayout6];
and my Layout6View looks like,
#implementation KCTLLookLayout6View
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self = [[[NSBundle mainBundle] loadNibNamed:#"Layout6"
owner:self
options:nil] lastObject];
self.frame = frame;
}
return self;
}
-(void)layoutSubviews{
[super layoutSubviews];
for (UIView *view in self.subviews) {
if (view == self.imageTopRightCorner) {
view.frame = CGRectOffset(CGRectMake(0, 0, /*(self.frame.size.width/2)-20, (self.frame.size.height/3)*/30,30), 0, 0);
}
}
}
#end
When I'm running this, the custom view didn't resized. It's spread all over the table view(not only inside the cell).
Is there a way to fix this?
Try:
[cell.contentView addSubview:lookLayout6];
Change the Size property of xib view. By default it is Inferred, make it Freeform and check.
I currently have a storyboard linked to a ViewController (.h and .m). Inside the storyboard (Main View), I have created another UIView that takes about half of the top screen. I have assigned that to a custom Class. The custom class has a .h .m and XIB file. A specific code fragment in my custom class contains the following:
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self){
[[NSBundle mainBundle] loadNibNamed:#"myXIB" owner:self options:nil];
NSLog(#"Width before: %f",self.bounds.size.width);
NSLog(#"Height After: %f",self.bounds.size.height);
//[self setNeedsLayout];
//[self layoutIfNeeded];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, 44)];
[self.view addSubview:searchBar];
CGRect newFrame = self.view.frame;
newFrame.size.width = self.bounds.size.width;
newFrame.size.height = self.bounds.size.height;
[self.view setFrame:newFrame];
[self addSubview:self.view];
}
return self;
}
The code currently creates a UISearchBar and add its to the sub view in my story board. My problem is related to calculating the width. The UISearchBar takes the argument for the width to be:
self.bounds.size.width
This calculates the frame drawed in the storyboard. However because the UIView inside my story board has constraints, the frame is not the final width. E.g. If i drawed 200px width in the story board, my code will retrieve the 200 and set the UISearch bar as 200 width. But in theory, the constraints will kick in and set the width to the size of the device e.g. 600px. So my question is, how can I find the updated width?
I have tried:
[self setNeedsLayout];
[self layoutIfNeeded];
They did not seem to work. Please can you suggest ideas?
-(void)layoutSubviews
{
[super layoutSubviews];
NSLog(#"Width before: %f",self.bounds.size.width);
NSLog(#"Height After: %f",self.bounds.size.height);
}
This should give you the actual size
I have a UIScrollView (similar to that seen showing the featured items on the App Store) which has 3 views, with xibs, loaded into it. Everything works find except I can get the UIButtons which I have on the xibs to fire. I guess I am missing something obvious just can't see it. I've tried various answers on here and other places to no avail.
Thanks in advance
Code from viewDidLoad on ViewController containing scroll view
LSCWInfoView *view1 = [[[NSBundle mainBundle]
loadNibNamed:#"LSCW-InfoView"
owner:self options:nil]
firstObject];
CGRect frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size = self.activityPageControl.frame.size;
[view1 setFrame:frame];
[self.activityScrollView addSubview:view1];
ScrambledInfoView *view2 = [[[NSBundle mainBundle]
loadNibNamed:#"Scrambled-InfoView"
owner:self options:nil]
firstObject];
CGRect frame2;
frame2.origin.x = 320;
frame2.origin.y = 0;
frame2.size = self.activityPageControl.frame.size;
[view2 setFrame:frame2];
[self.activityScrollView addSubview:view2];
TestInfoView *view3 = [[[NSBundle mainBundle]
loadNibNamed:#"Test-InfoView"
owner:self options:nil]
firstObject];
CGRect frame3;
frame3.origin.x = 640;
frame3.origin.y = 0;
frame3.size = self.activityPageControl.frame.size;
[view3 setFrame:frame3];
[self.activityScrollView addSubview:view3];
_activityScrollView.contentSize = CGSizeMake(_activityScrollView.frame.size.width * 3, _activityScrollView.frame.size.height);
EDIT - Code for one of the views loaded into the scroll view (other 2 are the same)
#import "LSCWInfoView.h"
#implementation LSCWInfoView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
- (IBAction)lscwPlayButtonPressed:(id)sender
{
NSLog(#"YEP");
}
#end
Screenshots
This was fixed by setting the frame size of the view before it is added to the scrollview