I have a UIView controller and a UIView called GCView.
If my code is just this :
self.view = [[GCView alloc] init];
I can see my custom view.
When I drag and drop a UIView in the storyboard, assign it to a property called customView
and use that code:
self.customView = [[GCView alloc] init];
nothing is shown.
I want to use the second approach, because it is more convenient to have some stuff inside the UIView created and handled dynamically, and the others to be statically inside the storyboard and handled in the UIViewController.
Make sure your view object in the story board is of class GCView. This will call initWithCoder: in your GCView class when the view loads. Once you have that, remove this:
self.customView = [[GCView alloc] init];
as the object will have already been initialized by the storyboard loading. Make sure all of your initialization calls in the GCView class are in initWithCoder: and not init.
Related
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 an UIViewController. Inside the view controller there is a custom UIView class object added as subview. Now, inside the custom UIView class, I have a search display controller. When I do this
SearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:SearchBar contentsController:self]
it is giving warning as self is UIView object, not UIViewcontroller object, so search result is not showing.
I want to show search result from the UIView only.
How can I do that? Any kind of help is appreciated.
You need to first create a UIViewController with the custom view you need and then add this controller's view to your view. Something like:
[self.view addSubview:[[[UIViewController alloc] init] view]];
Remember that UISearchDisplayController have a UITableView and that needs a UIViewController as a delegate. Just a UIView will not do.
I would like to use my viewDidLoad function in my tableViewController.
How can I make viewDidLoad run in my controller?
tableViewController = [[TableViewController alloc] init];
UITableView *tableView = [[UITableView alloc] init];
tableViewController.view = tableView;
....
From Apple documentation:
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.
So you can try to instantiate it from NIB or overwrite the loadView method. Another step from Apple documentation:
If you cannot define your views in a storyboard or a nib file, override the loadView method to manually instantiate a view hierarchy and assign it to the view property.
viewDidLoad will be called when the view is actually loaded, which will happen after you present your view controller, by, e.g.:
adding it to a navigation controller,
adding it to a tab bar controller,
presenting it modally.
This is the missing bit in your code. If you explain how you would like to present your view controller, I may help further. Also, have a look at this: Presenting View Controllers.
(I assume the fact that you tried to override the view property of your table view controller was just an attempt "to make things work" -- but you do not need to do anything about that, the view controller will be correctly set up with a table view inside of it).
tableViewController = [[TableViewController alloc] init];
tableViewController.tableView // This is your newly generated tableview
viewDidLoad will be called after you assign the tableView to another parentview
I don't understand the mechanism of loadView: function (this function is in UIView).
I created a project as below:
First, I created a iPhone's window-based project.
Then, I created a UIView subclass
Next, I created a UIViewController subclass, with no xib.
Lastly, in the loadView: function of the class I created in the third step, I designate the UIView object (in the class I created in the second step) as the view variable of the UIViewController object (in the third step).
If I omit the last step, and place the statement NSLog(#"test LoadView"); in the loadView: function, then when the project is run, the statement NSLog(#"test LoadView"); is invoked continuously, result in the run is overflow.
Please explain me! Thank you!
loadView: is only invoked when the view property is nil. Use this when creating views programmatically. default: create a UIView object with no subviews. For ex -
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
[view setBackgroundColor:color];
self.view = view;
[view release];
}
By implementing the loadView: method, you hook into the default memory management behavior. If memory is low, a view controller may receive the didReceiveMemoryWarning message. The default implementation checks to see if the view is in use. If its view is not in the view hierarchy and the view controller implements the loadView: method, its view is released. Later when the view is needed, the loadView: method is invoked again to create the view.
Not sure why you want to use loadView: but you can do just as much in viewDidLoad:
Reference -
Why is this iPhone program not calling -loadView?
loadView
Hope this helps.