Defining custom UIViews in storyboard - ios

I want to show my own custom UIView in storyboard. By far I have done following but my custom view is not showing up.
Dragged and dropped a UIView instance in my screen.
Defined the class for this UIView as my custom class.
Have connected this UIView with an IBOutlet in my view controller.
I even tried with below code in viewWillAppear.
self.myView = [[MyCustomView alloc] initWithFrame:frame];
This works if I create an instance of my custom view and add as a subview to my IBOutlet property for my view. So, below code is working but I want to keep track of only my IBOutlet iVar and do not want to play with another object for changes on my custom view:
self.myExtraView = [[MyCustomView alloc] initWithFrame:frame];
[self.myView addSubview:self.myExtraView];
Any idea how to do this in a better way so that I could have just one reference of my custom view and could change properties on it as per will.

Found the issue. With storyboard we must initialize anything in initWithCode method. I was implementing the regular init method.

Related

When subclassing UIView with a XIB file, why do I need to have a contentView property as a subview to display the XIB?

So I have a subclass of UIView - let's call it CustomView - with a XIB file for the layout of its subviews.
In interface builder I set the Custom Class of the top level view to CustomView and made a class method to load the XIB and return that top-level view when I need to use it elsewhere in the app.
CustomView.m
+(instancetype)newCustomView
{
CustomView *customView = [[[NSBundle mainBundle] loadNibNamed: #"CustomView" owner: nil options: nil] firstObject];
...
return customView;
}
ViewController.m
-(void)viewDidLoad
{
...
CustomView *firstCustomView = [CustomView newCustomView];
[self.view addSubview: firstCustomView];
}
This all works and I can access CustomView's outlets just fine, but it feels pretty hacky. Looking into the conventional way to initialise a UIView subclass with an associated XIB I found a single article using this same method, but the majority of tutorials use some variation of:
Set the File's Owner to the UIView subclass. (Don't set a custom class for the top-level view)
Add a contentView outlet to the class and set it to the top-level view in interface builder.
Make a method to load the Nib and add the contentView as a subview of the class.
Call this method in both initWithFrame: and initWithCoder:.
This works too, but I don't understand is why it's necessary to have a contentView property set to IB's top-level view as a subview. If CustomView is already a UIView why can't I just set itself to that top-level view? Wouldn't that be more straight forward? I feel like the more I try to understand it the less it makes sense.
Cheers for any help!

access UIView In UIViewController Storyboard

I want to ask, who the Views in the Storyboard, which are attached to a UIViewController are accessable. Who to add them to the UIViewContoller to its views programmaticliy with Objective C. The appear in the Storyboard like this:
and are in the tree in the same hirgachy as the UIViewController Node.
You can take outlet of that view in respective view controller class as you you take outlet of view put in viewcontroller's default view.
Then in your viewDidload you can add that view to your default view!
For example your outlet is outterView then in viewDidload,
[self.view addSubview:self.outerView];
Second thing if you are adding view in viewDidload and you need your view's size as screen size than in viewDidappear you can do like,
self.outerView.frame = self.view.frame;
Ok it was my fault, sorry folks.
I also need an IBOutlet to the to the ViewControllers view. So connect the them in InterfaceBuilder first and give the View the the customClass.
Referencing Outlets
view->UIViewContoller
HelloUIClass *viewThis = [[HelloUIClass alloc] init];
[self.view addSubview:viewThis]
…this is a start not sure about that.
You just have to do it right in Interface Builder!
DRAG AND DROP! the Reference Outlet in to your Headerfile under the #interface.
Open both windows. The Storyboard and your Controller Class .h file.
Grap an REFERENCING OUTLET from the View in File Inspector or right Mouse click and draw line into your Sourcecode. If you have done your class properly it will hook under your #interface line. AfterDroping you have give it a name "myViewInIB" and than you have just something like this:
#interface UIMainView : UIViewController;
#property (weak, nonatomic) IBOutlet UICoustomView *myViewInIB;
than you can use it normaly in your Class (Obj C)
[self.view addSubview:self.myViewInIB]
you said you have class of that view so you can do like this
Suppose your class name is View then,
1) in storyboard give name "View1" of class to view
2) you need to create Class if you want to give size programatically
3) for view size you can also use constraints instead of frame.
View1 *objView = [[View1 alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];
viewObj.center = self.view.center;
viewObj.backgroundColor = [UIColor redColor];//so you can find view easily
[self.view addSubview: objView];

How to set backgroundColor in loadView?

I want to override the loadView method of my custom view controller in order to customise the view that is being shown. For that custom view I want to apply the background color that was set in the Storyboard editor.
If I for example implement loadView like this:
-(void)loadView{
self.view = [[MyCustomView alloc] init];
//Do some initialisation work for the custom view
//...
}
Then the resulting view has a black background. However, if I only call the default implementation:
-(void)loadView{
[super loadView];
}
Then the orange background color (see screenshot) is applied to the view. How can I get the color that was set in Storyboard editor? I would like to do something like this (pseudo code):
-(void)loadView{
self.view = [[MyCustomView alloc] init];
self.view.backgroundColor = [self colorThatWasSelectedInStoryboardEditor];
//Do some initialisation work for the custom view
//...
}
How does apple achieve that in the default implementation of loadView?
Since you apparently really want to use "loadView" here instead of "viewDidLoad", AND Apple's documentation for loadView says NOT to call "super", you will need to "hide" your custom color somewhere else. E.G. some other view (e.g. a hidden one?) in your ViewController, where it's connected to an IBOutlet and where you can extract it via the view's ".backgroundColor" property.
Or you will need to set your ".backgroundColor" property via good ol' UIColor methods like "colorWithRed:green:blue:alpha:".
All your views from the Storyboard are laid out before viewWillAppear:, which means, in viewDidLoad you don't have them yet. Try moving your code to viewWillAppear:, or even better, to viewWill/DidLayoutSubviews and than self.view.backgroundColor will give you the one you set in the IB.
To answer the question in your comment, go to the IB, select your view, go to the Identity Inspector tab under the Utilities (right) pane, and set a custom class to be MyCustomView. No need to implement loadView to do that.
e.g. a UIView that I have declared as a custom view class AGBlurView:

Should i create a view ( consisting UIButton, UILabel etc) in a separate UIView class or inside UIViewController?

I have a UIViewController say viewControllerA which contains some view element like UIButton, UILabel etc. Now my question is should I create those view elements in a separate UIView class and then add in UIViewController, or should I create those view elements directly inside the UIViewController. Accordingly to MVC isn't it appropriate to create view elements inside a separate UIView class and then add this in UIViewController?
The standard place to build the view hierarchy in a UIViewController is in the -viewDidLoad method. That method gets called whenever the UIViewController's view is created. The view controller's view will be loaded from the NIB/Storyboard if applicable; your outlets will be wired up; and then -viewDidLoad is called for you to perform further customization:
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *aLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0,0.0,100.0,40.0)];
[self.view addSubView:aLabel];
}
In Cocoa/Cocoa Touch you don't always want to subclass everything the way you would in, say, Java. There are often other preferred means of extending the functionality in built-in classes such as Objective-C categories, delegation, and pre-defined properties.
It's certainly possible to do this sort of thing another way, but this is the most "Cocoa-like" way to do it. Actually, the most "Cocoa-like" way would be to create the view hierarchy in Interface Builder, but if you want to do it programmatically this is the usual way.

Setup/instantiation of IB subview with custom class

I have a .xib file for my viewController. It contains a TableView and a UIView. The UIView is backed by a custom class - CommentsBarView (trying to position a small bar with a comments field underneath my tableView).
So in my Document Outline list I have:
view
tableView
comments bar view
UITextView
UILabel
Custom class for "comments bar view" is CommentsBarView.
I have outlets connected from within CommentsBarView to the textfield and label.
(and from the ViewController to the tableView).
When I load my with controller with:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
I can access the tableView property and change the appearance of the tableVIew, however, from my commentsBarView initWithCoder I can not set the text value on my textView and label:
- (id) initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self.commentTextView setText:#"Helo, World!"];
[self.characterCountLabel setText:#"200"];
}
return self;
}
It seems as if these properties are not available at initWithCoder time.
If I manually, from my controllers initWithNibName, accesses self.commentsBar.label.text = 200, there is no problem.
Am I experiencing a timing issue where the views are not ready yet or can I not nest a view inside a viewControllers view and have it backed by a custom UIView subclass?
IB is confusing me a bit.
Thanks for any help given.
When loading from a XIB file, the IBOutlets are not ready in the init methods of the objects being unarchived.
You need to override awakeFromNib in your CommentsBarView to have access to the ready and connected IBOutlets.
Once you get used to IB it becomes better. Since Cocoa is a MVC (Model-View-Controller) you should probably not create a UIView subclass and set your UIView to it. You should probably put the UIView back to just a UIView. I generally subclass a UIView if I need to have a customized look. For example; a good time to subclass a UIView is if you want it to have a gradient. Then you can reuse your subclass for any UIView you wish to show the gradient.
In your case you are trying to "control" the UITextView and UILabel. You can instead wire-up outlets of your UITextView and UILabel directly to your UIViewController (File Owner). That is the "controller" of the MVC in this case. Think of your UIView as a container that is simply holding the two controls for this example. Now you can use the viewDidLoad method or some other method of you UIViewController to set the values of you UITextView and UILabel. It is generally the UIVeiwController that interprets the data from the Model in Cocoa and places the data where it needs to be. It is not a rock-solid rule, but a good one.

Resources