I created a UIView in a separate subclass of UIView and with an xib.
I have a UIViewController with a UIView in storyboard and I want to set custom UIView to this UIView.
I modified class name in storyboard UIView to the class name of custom UIView. I am getting the UIView on the result but with the frame size of custom UIView. I added correct constraints in the custom xib. and some touch gestures not working as desired because of the wrong frame etc.
Please suggest me if anything wrong I did.
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// Load the UIView from Interface Builder
[[NSBundle mainBundle] loadNibNamed:#"TMPhotoEdit" owner:self options:nil];
// Add UIView to current UIView object.
[self addSubview:self.view];
}
return self;
}
self.view is the same view object I created a variable for it.
I want the frame to set as same as the one i am using in storyboard.
Solution to get it work using code also helps me a lot. I mean, without IBOutlet in storyboard, just adding this UIView with some frame set to it.
If I call initWithFrame, I can't set the xib like what I am doing with initWithCoder above and initWithCoder is not being called if I use initWithFrame in code.
Assuming you have an instance of the view you want to resemble in size
self.view.frame = CGRectMake(otherView.frame.x, otherView.frame.y, otherView.frame.width, otherView.frame.height);
Actually what you are doing is not correct but anyway you should load the custom view nib like this
self.view = [[NSBundle mainBundle] loadNibNamed:#"TMPhotoEdit" owner:self options:nil][0];
Again this is not correct, why do you need it anyway? but it shall solve your nib loading issue.
Related
Here's the situation: I have a VC that has a Custom UIView inside it. This Custom UIView has an .xib file, which contains 2 UIImageViews. I'm trying to get those 2 UIImageViews to scale to same size across different screen size by using AutoLayout. However, when I launch my app the images in my Custom UIView go out of bounds of the Custom UIView's super View (which is the VC) container size. Please, help. Here are some pictures to explain the issue in better detail.
My code in Custom UIView:
#implementation CustomTwoImagesSelectedUIView
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self load];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self load];
}
return self;
}
- (void)load {
[[NSBundle mainBundle] loadNibNamed:#"CustomTwoImagesSelectedUIView" owner:self options:nil];
self.lastImageView.layer.cornerRadius = 5.0f;
self.lastImageView.clipsToBounds = YES;
self.secondToLastImageView.layer.cornerRadius = 5.0f;
self.secondToLastImageView.clipsToBounds = YES;
[self addSubview:self.twoImagesSelectedView];
}
You have set the cliptobounds property of the imageviews but the bound of imageviews itself is not set properly I guess. You need to carefully set layout constraints in the .xib file for imageviews. Also. When you add the customImageViews to some view controller, or superview. You also need to set the layout constraints for customImageViews with respect to its superview.
I have try AutoLayout in the custom UIView, but it can not work too. I think it is a bug from Xcode, and I finally found this article:Create an IBDesignable UIView subclass with code from an XIB file in Xcode 6
In the article, I found it use autoresizingMask instead of AutoLayout. It is a good way to fix the UI display problem. I hope it can helps you.
- (void)load {
[[NSBundle mainBundle] loadNibNamed:#"CustomTwoImagesSelectedUIView" owner:self options:nil];
self.lastImageView.layer.cornerRadius = 5.0f;
self.lastImageView.clipsToBounds = YES;
self.secondToLastImageView.layer.cornerRadius = 5.0f;
self.secondToLastImageView.clipsToBounds = YES;
[self addSubview:self.twoImagesSelectedView];
self.twoImagesSelectedView.frame = self.bounds;
self.twoImagesSelectedView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
I am trying to add a custom UIView that I created in XIB, to my view controller in my main.storyboard as a subview. How can I do this?
matchScrollView (tag 1) is the UIScrollView in view controller in main.storyboard, while matchView (tag 2) is the custom UIView I created in another XIB file.
With the press of a button i want to have the custom UIView added to the UIScrollView as a subview. But how can i actually make it show up on display? I guess i have yet to alloc and init it, along with indicate position and such, but how can i do that? I tried different ways without success. I can create UIViews programmatically, but have yet to find a way to just load the UIView from XIB.
-(IBAction) buttonTapped:(id)sender {
UIScrollView *matchScrollView = (UIScrollView *) [self.view viewWithTag:1];
UIView *matchView = (UIView *) [self.view viewWithTag:2];
[matchScrollView addSubview:matchView];
}
The reason that I am creating my custom UIView in another XIB file instead of directly implementing it on my main.storyboard view controller, is because I want to re-use the same view multiple times. So the UIScrollView has a numerous subviews of UIViews.
I was hoping I could create numerous instances of MatchView and add them all to matchScrollView as subviews.
The issue you are having is completely normal. The way Apple designed it doesn't allow to reuse custom views with their own xib into other xibs.
Lets say you have a custom view named HeaderView with a custom xib named HeaderView.xib. And lets say you want to be able to, in another xib named GlobalView.xib, drag a subview and specify its class to be of type HeaderView expecting it to load that view from HeaderView.xib and insert it inplace. You can do it like this:
A) Make sure File's Owner in HeaderView.xib is set to be HeaderView class.
B) Go to your GlobalView.xib, drag the subview and make it of class HeaderView.
C) In HeaverView.m implement initWithCoder, if after loading the view there aren't subviews means it got loaded from GlobalView, then load it manually from the correct nib, connect the IBOutlets and set the frame and autoresizingmasks if you want to use the GlobalView's frame (this is usually what you want).
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self.subviews.count == 0) { //means view got loaded from GlobalView.xib or other external nib, cause there aren't any subviews
HeaverView *viewFromNib = [[NSBundle mainBundle] loadNibNamed:#"HeaverView" owner:self options:nil].firstObject;
//Now connect IBOutlets
self.myLabel1 = viewFromNib.myLabel1;
self.myLabel2 = viewFromNib.myLabel2;
self.myLabel3 = viewFromNib.myLabel3;
[viewFromNib setFrame:self.bounds];
[viewFromNib setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[self addSubview:viewFromNib];
}
return self;
}
I am trying to create a custom UIView class with an associated Nib (.xib) file to help with layout and creation.
Right now, no subviews in my custom view appear, even though they exist in my nib file and are hooked up properly to my custom view class via IBOutlets.
I tried going through the following other answer:
Load custom UIView with XIB from a View Controller's view using IB
and this one:
How do I get a view in Interface Builder to load a custom view in another nib?
and this one:
http://soulwithmobiletechnology.blogspot.com/2011/06/create-uiview-with-nib-file-in-xcode-4.html
but the method [[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil] seems to call -[initWithCoder:], leading to an infinite loop.
Please let me know what other details to include to help solve this bug!
UPDATE 1: Do I need to lay out my subviews via -[layoutSubviews]? Does my nib file actually not lay it out? If so, then what is the point of the nib file?
Open any of your view controllers and paste this code into your viewDidAppear method:
NSArray * allTheViewsInMyNIB = [[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil]; // loading nib (might contain more than one view)
MyCustomView* problemView = allTheViewsInMyNIB[0]; // getting desired view
problemView.frame = CGRectMake(0,0,100,100); //setting the frame
[self.view addSubview:problemView]; // showing it to user
That's all you have to do, to present a view. If you want to interact with this view — you have to declare MyCustomView* problemView in your class' interface, not in the method.
First, I have a exist Asset.m/Asset.h, it is the subclass of UIView. Then I create a empty xib file and change xib's file's owner class to Asset. Then I create a view and a label to this xib, and I can drag and create IBOutlet in UIView.
IBOutlet UIView *videoOverlay;
IBOutlet UILabel *videoTimeLable;
Then I want to add videoOverlay to Asset.m's view using addSubview.
self = [super initWithFrame:CGRectMake(0, 0, 0, 0)];
[self addSubview:videoOverlay];
But the view -- videoOverlay do not show up.
I print out size of videoOverlay, all 0:
NSLog(#"width =%f height= %f", videoOverlay.frame.size.width, videoOverlay.frame.size.height);
Why ?
Finally, I find the solution by myself. Use under code to add this view (videoOverlay and videoTimeLable belong to this view )in:
UIView *thumbs;
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ELCAsset" owner:self options:nil];
thumbs = [nib objectAtIndex:0];
[self addSubview:thumbs];
then videoOverlay and videoTimeLable can show up.
I have a grid on screen. It is an instance of a UIView subclass. In cells in the grid I want to add instances of subviews - another custom subclass of UIView - as the user interacts with the app. The subview itself is something I want to design in an XIB. Its controls represent state for that particular cell. It consists of a couple of UIControls (say a label and a button).
I already know I can load NIBs dynamically using
[[NSBundle mainBundle] loadNibNamed:#"MyNIB" owner:self options:nil];
and I know they'll work if I set the File's Owner property in the NIB to the view controller that's responsible for the view these subviews will be added to. I use this to add some external NIBs to a UIScrollview in the main app screen.
What I want to know is how can I do this dynamically? I want to say something like:
MySubviewCell * sv = [[NSBundle mainBundle] loadNibNamed:#"MyNIB" owner:self options:nil];
[sv setFoo:#"Foo"];
[sv setBar:123];
[sv setFrame:myrect];
[mainView addSubview:sv];
But of course loadNibNamed doesn't return me the subview instance, instead it returns an array of all the controls in the view.
EDIT File's Owner in the MySubviewCell NIB will be a problem: there isn't one, and there can't be: I don't know how many I'll need. Should I be using something like an ArrayController?
EDIT 2 Please ignore the previous edit; I've left it in as the answer refers to it but it's not the problem I thought it was.
Can I do this?
Thanks
This is commonly used when designing table view cells in a nib. You've got two options:
The object at index 0 of the returned array will be the "root" object in your nib.
Create an outlet in your view controller of type MySubviewCell. Set your file's owner class in the nib to your view controller, and link the outlet to the element in the nib you are interested in. When you load the nib with owner self, the outlet becomes populated. You can then configure it, add it to your array, and set the outlet back to nil to prepare to load the nib again for the next instance.
Try to access to first object in that array:
MySubviewCell * sv = (MySubviewCell*)[[[NSBundle mainBundle] loadNibNamed:#"MyNIB"
owner:self
options:nil]
objectAtIndex:0];