I created MyCustomView which has two labels. One at left and one with right align and at right. It has about 30px height (it's not important). I connect it to xib and it works. In .xib I set main view width to 400px and set autolayout constraints for labels.
Now the problem. When I added to my controller in IB with UIView and set class to MyCustomView I see left label but right label is out of screen. I set constraints right but It doesn't work. When I tried to resize MyCustomView in .xib by mouse and moving with edges it's okay but when I set width value "manually" in right column it doesn't layout right (it doesn't change at all). Where is the problem? How can I fix this?
#implementation MyCustomView
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit
{
self.backgroundColor = [UIColor clearColor];
self.view = [[[NSBundle mainBundle] loadNibNamed:#"MyCustomView"
owner:self
options:nil] firstObject];
[self addSubview:self.view];
//self.translatesAutoresizingMaskIntoConstraints = NO;
}
- (void)awakeFromNib {
[super awakeFromNib];
//[self setNeedsUpdateConstraints];
//[self setNeedsLayout];
}
#end
As you can see in comments I tried some ways but nothing helped.
New File --> iOS (Source) -- Cocoa Touch --> Next
Enter Name
Add code in MyCustomView.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
//self.view.backgroundColor = [UIColor redColor];
self.preferredContentSize = CGSizeMake(30.0, 400.0);
}
return self;
}
Related
I've really spent my hours for finding any approach about this problem.
I have;
CustomView.h that extends from UIView and is also IB_DESIGNABLE
CustomView.m for implementation of this view with override methods init, initWithCoder and initWithFrame
CustomView.xib that bound to CustomView class with all properties
And, I have :
CustomTableViewCell.h that extends from UITableViewCell
CustomTableViewCell.m that implementation of this cell
CustomTableViewCell.xib that bound to CustomTableViewCell class with all properties&outlets.
CustomTableViewCell.xib includes CustomView...
There is no any error, but the area of CustomView remains blank.
For view you need to do some work around.
Create a property and link your view in the XIB to it;
#property (strong, nonatomic) IBOutlet UIView *xibView;
Then have something like this:
- (void)awakeFromNib{
[super awakeFromNib];
[self commonInit];
}
- (instancetype)init{
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit{
//this will work if the view has the same name as the XIB
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
self.xibView.frame = self.bounds;
[self addSubview:self.xibView];
self.xibView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
Basically you have to load the XIB manually and add it to your custom view.
I'm following this video (except im linking the custom view in code not in IB), but I'll explain what's happening. I have created a custom view that extends off UiView. It is created from an xib file. Here is a photo of the xib file in interfacebuilder:
Notice that the file owner is already linked to my custom class.
Now I'll show you my custom class:
#import "CostcoLoginView.h"
#implementation CostcoLoginView
-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
self=[super initWithCoder:aDecoder];
if(self){
[[NSBundle mainBundle] loadNibNamed:#"CostcoLoginView" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
#end
And here is the header file for my custom view:
#import <UIKit/UIKit.h>
#interface CostcoLoginView : UIView
#property (strong, nonatomic) IBOutlet UIView *view;
#end
notice the one property I have: it's a view that is linked to the interfacebuilder xib file shown in the photo above.
Everything looks good so far. My goal now is to use this custom UIView as the inputAccessoryView of a UITextField I have. Here is the partial code:
usernameField.inputAccessoryView = [[CostcoLoginView alloc] init ];
Why is this not working? Nothing appears. Is it because of how I'm initializing the custom view? When I check in the simulator nothing appears. I tried toggling the keyboard but nothing appears. The rest of app works fine, but my custom view does not appear.
You have not add subview when you call init,and you forget to set frame of your view in xib.
so you may change your code to this and try.
#import "CostcoLoginView.h"
#implementation CostcoLoginView
-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
[self setup];
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
self=[super initWithCoder:aDecoder];
if(self){
[self setup];
}
return self;
}
-(id)init{
self = [super init];
if (self) {
[self setup];
}
return self;
}
-(void)setup{
[[NSBundle mainBundle] loadNibNamed:#"CostcoLoginView" owner:self options:nil];
self.view.frame = self.bounds;
[self addSubview:self.view];
}
#end
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 want to create a section header that loads a nib file and sets that as the header UIView. This nib file will also have an associated class where the outlets and actions are connected to so I want to load that class with the nib like normal.
I've scoured the web and found several similar answers but I can't get any to work for me. After playing around for a few days I managed to get the view to show correctly but it doesn't do anything despite adding connections and telling the text to show differently.
For example it should clear the section title text if it's init with nil and it does that yet it still shows the same text, attempts to change it doesn't reflect either and any connections made with the button aren't triggered.
Here is my view controller for the view
#interface ADUNewRowHeaderViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *sectionTitleField;
#property (strong, nonatomic) IBOutlet UIButton *addRowBtn;
#property(strong,nonatomic) NSString* sectionTitle;
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
title:(NSString*) titleOrNil;
#end
and here is the implementation
#implementation ADUNewRowHeaderViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil title:(NSString *)titleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
if(titleOrNil != nil)
{
[self setSectionTitle:titleOrNil];
}
else
{
[self setSectionTitle:#""];
}
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)setSectionTitle:(NSString *)sectionTitle
{
_sectionTitle = sectionTitle;
[[self sectionTitleField] setText:sectionTitle];
}
#end
in the actual table view controller it's listed as
#property(nonatomic, strong) ADUNewRowHeaderViewController* secHeader;
and in the implementation file under viewDidLoad as
[self setSecHeader:[[ADUNewRowHeaderViewController alloc] initWithNibName:nil bundle:nil title:nil]];
[[[self secHeader] addRowBtn] addTarget:self action:#selector(addNewRow:) forControlEvents:UIControlEventTouchUpInside];
and
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return [[self secHeader] view];
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return [[self secHeader] view].bounds.size.height;
}
this is the method declaration for the action
- (IBAction)addNewRow:(id)sender;
You should make a UIView, instead of a UIViewController, subclass. The .m would contain:
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
[self setUp];
}
return self;
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self setUp];
}
- (void)setUp
{
[[NSBundle mainBundle] loadNibNamed:#"YourNibName" owner:self options:nil];
CGRect frame = self.frame;
self.view.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
[self addSubview:self.view];
... do other initialisations here ...
}
And the .h:
#interface ADUNewRowHeaderView : UIView
#property (nonatomic, strong) IBOutlet UIView* view;
Then in the XIB: Make File's Owner of class ADUNewRowHeaderView, as usual. And connect the XIB's top-level View's Referencing Outlet to the view property above (i.e. in File's Owner).
You then have a UIView subclass you can place on another XIB (as a UIView which for which you set the Class to ADUNewRowHeaderView), or instantiate in code and add as subview.
(Alternatively you could create the UIView and it's subviews (buttons, labels, ...) in code; then you would not need a XIB. But this only works of course if the UIView is simple and has little own logic, and few UI elements that are easy to layout in code.)
I'm setting the backgroundColor of my UITableViewCell like this:
cell.backgroundColor = [UIColor colorWithPatternImage:
[UIImage imageNamed:#"background.png"]];
It looks fine except for the "end caps" of the cell. The end caps (where the rounded corners start) are colored differently like the middle portion of the cell. Do I need to provide images for the end caps too?
not really sure what the end caps are. but i would say if ur using an image for your cell it should take up the whole cell. and you should be defining the size of your cells at that point. see layout subviews below for what i mean
#import "CustomCell.h"
#implementation CustomCell
#synthesize primaryLabel,myImageView;
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// Initialization code
primaryLabel = [[UILabel alloc]init];
primaryLabel.textAlignment = UITextAlignmentLeft;
primaryLabel.font = [UIFont systemFontOfSize:20];
myImageView = [[UIImageView alloc]init];
[self.contentView addSubview:primaryLabel];
[self.contentView addSubview:myImageView];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
CGRect frame;
frame= CGRectMake(boundsX+10 ,0, 40, 40);
myImageView.frame = frame;
frame= CGRectMake(boundsX+70 ,5, 200, 25);
primaryLabel.frame = frame;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[myImageView release];
[primaryLabel release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end