I have aded a new View in my app, its just a .xib file
On button click i am calling this new view... AS
UIViewController *newView = [[UIViewController alloc] initWithNibName:#"Welcome" bundle: [NSBundle mainBundle]];
[self.view addSubview:newView.view];
It call successfully the new view.
I have set some labels and button newView that are shown on button click.
now the problem is this,
1- i have to send or pass some data to newView from main and also
2- when i connect a UILabel using CONTROL Drag in interface builder on selecting File's Owner Of newView with desired Label it gives me error on button click
'[<UIViewController 0x89d05b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key Users.'
'User' is the UILabel type variable In my .h file that is declared as
#property(nonatomic ,retain) IBOutlet UILabel *Users;
any suggestion or help would be appriciated
You're creating a UIViewController instead of your custom UIViewController subclass. What you should be using is:
MyViewController* vc = [[MyViewController alloc] initWithNibFile:...]
Also note that if you're using child view controllers, you should be calling addChildViewController with the newly created view controller so that the UIViewController methods are properly propagated to the child view controller.
One last note, none of this will work reliably before iOS 5, as up to that point child view controllers were strongly advised against.
It also sounds like you're not using a subclass for the child view controller, if you add properties or actions, you have to use a subclass.
Related
I’m using xcode 7 , I’ve a storyboard controller with an UIContainerView
When I’m trying to create an outlet to the controller there is this error "Use of undeclared type UIContainerView"
it’s not a bug of xcode 7 because there is the same error on xcode 6
i need to create an outlet because when i switch the segmented control i have to programmatically change the embed of the container
It's an error or i mustn't create an outlet for a container? It's seems that there is not something called UIContainerView in the library, it's strange
There is no such class called UIContainerView. You need to create an outlet of UIView and connect that to your container view.
You can switch the content of container view like:
// Property
#property (nonatomic, weak) IBOutlet UIView *container;
#property (nonatomic, strong) UIViewController *first;
#property (nonatomic, strong) UIViewController *second;
// Method that removes first vc from view and shows second vc
// Assumes first and second properties already initialized
- (void)showSecondVC
{
// Removes first view controller
[self.first.view removeFromSuperview];
[self.first willMoveToParentViewController:nil];
[self.first removeFromParentViewController];
// Shows second view controller
[self addChildViewController:self.second];
[self.second didMoveToParentViewController:self];
self.second.view.frame = self.container.bounds;
[self.container addSubview:self.second.view];
}
It is confusing because IB lablels it as UIContainerView, but it's type is really just a UIView.
UIContainerView is not a class, so you are getting error. Instead use UIView. Container view is actually a concept in storyboard, that allow you to do similar programming stuff:
Initialise a second view controller
Add it as child view controller
Add its view at location of container view with same frame.
When you add a container view then all above stuff is done automatically.
If you want to switch to different view controller then you will create multiple container view. Show and hide container views based on UISegmentedController's selectedIndex
Here is the scenario
Create new project Tabbed Application. Add new controller, TestViewController with XIB file, in the XIB file just add one button with text "TestViewControllerButton".
If I create a button in FirstViewController, and add an action to go to TestViewController, the button in XIB file is displaed.
TestViewController* vc = [[TestViewController alloc] init];
[self presentViewController:vc animated:YES completion:nil];
The problem is when I add TestViewController to tab controller (index 2, start from 0), it does not show the XIB (I mean, the button does not displayed).
Here are my steps. I add UIViewController in Tab Controller, then change the class to TestViewController in Identity Inspector. Then add Tab Bar Item to TestViewController and link it to Tab Bar Controller, so when the last tab is clicked, it linked to TestViewController. But the problem is, the button in the XIB is not displayed (I add the button in TestViewController.xib).
Yeah, off course I can add the button directly in Main.storyboard in my TestViewController, but the idea is I want to manage the UI in TestViewController XIB, and the main.storyboard just load the view in TestViewController image.
Ok, I add some screenshot to make understand. This screen runs well when I do programmatically, run in UIViewController (code above - self presentViewController:vc animated:YES completion:nil).
When I run from Tab
The setting I think is already correct (since it runs well in UIViewController)
Already set file owner to the TestViewController
Already bind the outlet
Thanks!
I think you are using the ViewController of size Inferred , Change it to iPhone 4 inch in Attribute Inspector (Simulated Metrics -> Size and set the button frame acc. to that .
Hope this help :)
Of course it will not show the controls. See, you are using two different view controllers at these places. In the xib, you have actually added your button and hence when an instance of your testViewController is created from the xib, it has the button and its associated action with it. However, in the case when you add a viewController in your storyboard and set its class to be that of TestViewController, all you are doing is setting the class type of the new view controller to be TestViewController. But you are not providing any information by which the storyboard can know that it has to create the new instance of testViewController from the image saved in its XIB. So it just crates a new view controller of type TestViewController, using its image from inside the storyboard (without the button in it).
So to get your view controller from the xib you will have to override initWithCoder: method inside your TestViewController implementation and return an instance of your viewController from the XIB. Something like:
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
return [self initWithNibName:nil bundle:nil];
}
I am having one view controller WebViewController and second is Settings. On tap of button i am adding Settings view controller as subview of webviewcontroller.
menusettings=[self.storyboard instantiateViewControllerWithIdentifier:#"SET"];
[menusettings.view setFrame:CGRectMake(0, 0, 700,600)];
[self.view addSubview:menusettings.view];
I have Webview Object in the
Webview controller
#property (strong, nonatomic) IBOutlet UIWebView *wrae_one;
and i am loading data in webview but when i cal function from Settings controller then the value self.wrae_one becoming null. Means when i add setting view controller as subview in webview controller then obejet of webview become null. Is there any way to main it value. In settings i am using this code for calling the function
self.home_webview=[[PRGVwebViewController alloc]init];
[self.home_webview loadWebviewController]
I think that PRGVwebViewController is the class from which the settingsviewcontroller is instantiated. So why do you re alloc the class? Doing this you are creating a new controller, but when you dismiss the settingsviewcontroller, you are seeing the first one.
You have to create a reference to the previous controller.
Maybe, the best way is to instantiate the WebViewController as a sharedIstance (singleton), so you can access to it (and only it) wherever you want.
This can be helpful: http://www.daveoncode.com/2011/12/19/fundamental-ios-design-patterns-sharedinstance-singleton-objective-c/
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.