I have a viewA is loaded from Xib.
My question is that how to subClass this viewA.
Every time when the my SubClass inited, and call [super init], it will return [viewA class].
Similar situation happened in Storyboard, when I want to subClass a viewController which loaded from Storyboard.
Related
I finally made the switch to Storyboards and i am having issues loading custom controllers which was pretty easy to do when using interface builder.
I have ViewControllerOne with two components: A UIView and UITableView as the subview.
I want the UITableView to be controlled by a custom tableview controller. If this was Interface builder i would have dropped a tableview controller onto the XIB, linked to the custom controller and made the connections and it would have been done.
Using storyboard, i don’t believe its possible to drop a UIViewController/UITableViewController onto a scene which already has a view controller, i relied on Objects to achieve this.
So i added a Object onto the scene and linked it to my custom tableview controller. I set up delegate/date source for my UITableView to point to the custom controller. I finally connected the UITableViews outlet to the custom controller.
When i compile this, the custom controllers delegate (for the table view) gets called but the viewDidLoad is never called.
The only way i can invoke viewDidLoad is if i move the UITableView out of ViewControllerOne. My understanding was that even though there is one view controller for a scene i can still manipulate the subviews using custom controllers.
Am i misunderstanding something or is there is a solution for this ?
Some screenshots
There is a bit of magic in that. Call self.view from awakeFromNib and flow will back to the rails
- (void)awakeFromNib
{
[super awakeFromNib];
// here comes the magic - call self.view and view will load as expected
NSLog(#"awakeFromNib %#", self.view)
}
you can call it from initWithNibName:bundle:
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
NSLog(#"awakeFromNib %#", self.view);
}
return self;
}
the point is to call self.view because apparently something is done inside.
If I have understood your question correctly:
1 Open the storyboard and navigate to the table view controller that you would like to be of your custom type.
2 Click on the identity inspector in the right hand side panel.
3 Set the class to what it should be.
I'm using Storyboard and trying to reuse a View for different ViewControllers.
For that, I created a custom .xib (MyCustomView.xib) and class (MyCustomView) as suggested pretty much everywhere.
In my Storyboard I set the custom view to be of type MyCustomView.
In MyCustomView.xib, set First Responder to MyCustomView.
In MyCustomView.m, I added the following method:
-(id)initWithCoder:(NSCoder *)aDecoder{
if ((self = [super initWithCoder:aDecoder])){
UIView *myCustomView = [[[NSBundle mainBundle] loadNibNamed:#"MyCustomView" owner:self options:nil] objectAtIndex:0];
[self addSubview: myCustomView];
}
return self;
}
Problem is, [self addSubview: myCustomView] adds a new MyCustomView to existing MyCustomView, so the view is added twice.
How can I get rid of one of the two?
EDIT
My question is not really clear, so I thought some screen caps would help.
Here is my Storyboard with a custom view. Custom class is set to MyCustomView.
(I also added a grey background and a label for testing purpose only)
Now, in MyCustomView.xib, I set File's owner to be of Class MyCustomView:
And add outlets for title Label and imageView:
With the initWithCoder method as written above, this works fine, except when I debug I can see this:
So self is of course of type MyCustomView, as chosen in the Storyboard, but it contains 2 subviews :
First is the test label from my storyboard
Second is the view from MyCustomView.xib, itself containing a Label and image view. That's this view I want to get rid of.
What is self ?
Here, it is the MyCustomView you just instantiated. So, you're adding a new UIView (not MyCustomView) to your new MyCustomView instance created by the initWithCoder method.
initWithCoder is the method called when loading your storyboard view.
If you want to instantiate a new MyCustomView in your MyCustomViewController you have to call
MyCustomView *newInstance = [[MyCustomView alloc] init];
[self addSubview:newInstance];
Where self is the instance of MyCustomViewController in your storyboard.
EDIT
OK, I understand better your question.
If you want to load the MyCustomView nib file, you don't need to create a class for it (except if you have specific variables you want to access in it.
Just do what you're doing here, but in the view controller, which will be the self. :)
You might want to have a look at : How to load a UIView using a nib file created with Interface Builder
EDIT 2
Ok, I think I get it :
delete the MyCustomView in your Storyboard.
create a class MyView or whatever which you attach to the view named "View" in your Storyboard.
in the init method of your class you instantiate your MyCustomView nib
add the resulting UIView to the views stack like you did it.
self will be MyView (present in the Storyboard), MyCustomView won't appear in the storyboard but created programmatically in the init method of MyView.h
You will have to add constraints programmatically. Here is a post that can be helpful: Adding View Programatically With Auto Layout Gives 'NSGenericException', reason: 'Unable to install constraint on view
I am adding on screen a UIView in this way:
ViewController2 *detailViewController = [[ViewController2 alloc] initWithNibName:#"MJDetailViewController" bundle:nil];
[self presentPopupViewController:detailViewController animationType:MJPopupViewAnimationFade];
since MJDetailViewController is a nib and holds a UIView, I have created a custom class of UIView and selected it as class for the view in the inspector. When the window is loaded, the UIButtons do actions in the class that has been created, but the IBOutlets don't work. Even if I decided to add a UIButton programmably, it doesn't appear on screen. Why is this?
I thought of changing the UIView to a UIViewController, but it won't work because you can't present it with an animation.
I suspect you haven't set up the nib objects correctly.
In addition to setting the class of your UIView subclass you need to configure the 'File's Owner' and connect the views to it. You do this by selecting the file owner and setting its' class (this is done the same as setting the view's class). In your case the class of the file owner should be ViewController2.
Hopefully this screenshot explains this better:
Also you can simplify things a bit by using UIViewController nib naming conventions. If you give your nib the same file name as the view controller then you can specify nil as the nibName:. For example, if you name your nib ViewController2.xib then you can do this:
ViewController2 *detailViewController = [[ViewController2 alloc] initWithNibName:nil bundle:nil];
This approach is preferable as it means that the nib filename becomes an implementation details which calling code does not need to know about.
I have a custom UIView (MyCustomUIView) which is built using Interface Builder. I'd like to place this custom view in MyViewController's view, which is also designed using IB. I've placed an UIView as a subview in MyViewController's XIB and set it's class to MyCustomUIView. The problem is, when I run the code, only a blank view appears. (When I instantiate MyCustomUIView in code, it displays well.)
I'm only overriding the initWithFrame: method the following way in MyCustomUIView.m:
- (id)initWithFrame:(CGRect)frame
{
[[NSBundle mainBundle] loadNibNamed:#"MyCustomUIView" owner:self options:nil];
self = self.view;
return self;
}
What should I do to make the view load properly? How should initWithCoder: look like?
You are correct. IB uses initWithCoder. initWithCoder should look very similar to your other init methods:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// CUSTOM INITIALIZATION HERE
}
return self;
}
Once you assign your class within IB, you won't need to instantiate it from the bundle unless I'm misunderstanding your intention.
Do not put anything in the view part of the view controller in IB. Instead, set the nib name for the view controller in IB to the name of the nib containing the view. In the nib containing the view, set the file's owner to the view controller class and hook up its view property to the view.
The result will be that when the view controller is instantiated, if it is instantiated from the nib (which you have not proved is what's really going to happen, but let's just say it is), it will find the nib and load the view from it.
Basically the rule is that it makes no difference where a view controller comes from, it will go through the same steps looking for its view in the same order, as I explain in my book:
http://www.apeth.com/iOSBook/ch19.html#_view_controller_and_view_creation
and in this webcast:
http://www.youtube.com/watch?v=zIufcKpDIRo
Hy
i have two classes uiviewcontroller and uiview. I have one view controller. Inside i have uiview. Inside uiview i have textfield and when i write a text and click done i need to refresh uiviewcontroller.
I tried with this in uiview class:
-(IBAction)textFieldReturn:(id)sender
{
ViewController *vc = [[ViewController alloc] init];
[vc viewDidLoad];
}
i need refresh the same as you click the button and open viewcontroller.
I am guessing you mean that you want to "refresh" the view, not the view controller. To do that simply call [self setNeedsDisplay] from the view, or [self.view setNeedsDisplay] from the view controller. Also make sure that the textfield is a subview of the uiview. Either do that in the nib file or in code by calling [self addSubview: (textfield here)].
Also, if you want to access the view controller from the view you will need to create an IBOutlet, simply allocating a new ViewController object within the view does not mean that the created view controller controls the view. Hopefully that makes sense. I'd recommend going through some ios starter tutorials as well. Just google that there are a lot.