Protocols & Delegate when using ContainerView - ios

I have a UIViewController (root) with a ContainerView that loads a nib programatically:
UIView *containerView = [[[NSBundle mainBundle] loadNibNamed:#"KeyboardView"
owner:self options:nil] objectAtIndex:0];
[self.view addSubview:containerView];
I have a class file (.h and .m) hooked to this .xib file (UIView).
My .xib file (UIView) has a button and an action.
When this action is invoked and executed I removeFromParent my .xib file.
How can my ViewController.m (root) handle the exact time I removeFromParent my nib file?
I tried to use Protocol & Delegate but it failed.
I tried to set delegate=self on prepareForSegue Method but was unsuccessful.
My question is:
My UIViewController (root) invokes my keyboard (.xib) programatically.
All action in my keyboard are handled by the class hooked to the .xib.
After action’s job is done I removeFromParent the .nib file (I simulate a dismiss).
How can methods in ViewController.m (root) know that I dismissed my .xib file?

I'm not exactly sure what you are doing here, but I think I understand your question.
In your interface, declare a weak property for the keyboard view.
#property (weak, nonatomic) UIView *keyboardView;
Then when you load the keyboard
UIView *containerView = [[[NSBundle mainBundle] loadNibNamed:#"KeyboardView"
owner:self options:nil] objectAtIndex:0];
[self.view addSubview:containerView];
self.keyboardView = containerView;
Now you can test self.keyboardView != nil to know if the keyboard is loaded.
This works because keyboardView is weak so when it's removed from it's parent view the property will be set to nil.
NOTE: No protocol or delegate is needed.

Related

How to load view of xib file in another view controller

Xib File
#interface SearchingPropertyViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIView *searchingView
i added the below code to the button action in another ViewController
SearchingPropertyViewController *ps = [[[NSBundle mainBundle] loadNibNamed:#"SearchingPropertyViewController" owner:self options:nil] objectAtIndex:0];
[self.view addSubview:ps.searchingView];
I just wanted to load searchingView in another view controller
Try this! Simple solution :) Please find view controller loadview method. https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview
SearchingPropertyViewController *searchPVC = [[SearchingPropertyViewController alloc]initWithNibName:#"SearchingPropertyViewController" bundle:nil ];
[searchPVC loadView];
[self.view addSubview:searchPVC.textLabel];

UIViewController in storyboard with nib file

Hi can I ask if can I mix the xib with my UIViewController in storyboard? Like they share a controller in their files owner because I'm planning to create a expandable view by using nib as the expandedview and I want to pass a value from nib file to the UIViewController in storyboard. Thanks.
I don't recommend you mix xib and view controller from storyboard and hook them all together.
If you want to add a UIView as an extended view to your view controller you can do something like this:
// Load the first view inside our xib from main bundle
UIView *view = [[NSBundle mainBundle] loadNibNamed:#"nib_name" owner:self options:nil][0];
// Define new X,Y to our view
float new_x_position = 0;
float new_y_position = 400;
view.frame = CGRectMake(new_x_position, new_y_position, CGRectGetWidth(view.frame), CGRectGetHeight(view.frame));
// UILabel inside our nib, '111' is the tag we set to our UILabel
UILabel *label = (UILabel*)[view viewWithTag:111];
// Add our view to the current view as a sub view
[self.view addSubview:view];
I hope I understood you correctly.
In storyboard you are not provided with xibs, but if you want to use them to load from nib then use :
MyViewController *viewController = [[MyViewController alloc] initWithNibName:#"CustomDownloadedXib" bundle:nil];

Using custom View with Storyboard without adding it twice

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

Connect a new xib to a class that inherits from UIView

I'm developing an iOS app with latest SDK.
I want to create a custom UIView and set layout using a XIB file.
To this XIB, I have added four UIButtons using Interface Builder.
Now I want to connect these four buttons to my custom UIView class and manage there IBActions. This is very important, I have to do it this way.
To load the xib I do:
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder]))
{
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:#"MyCustomView"
owner:self
options:nil] objectAtIndex:0]];
}
return self;
}
I also have a storyboard and I have added an UIView to main ViewController using Interface Builder.
My question is: What do I have to do to connect the new XIB file to my custom UIView on Interface Builder?
I think I have to open this new xib on Interface Builder and set main ViewController as File's Owner, and set my custom UIView class as class for the view on this new XIB, but I'm not sure.
And, on main ViewController change the class for this new view to my custom UIView.
In Interface Builder, set the custom class to your CustomView.Make the connections to this custom class. In the whichever view controller you want to use this xib, Simply load the nib using loadNibNamed:owner:options: method.
CustomView *cView = [[[NSBundle mainBundle] loadNibNamed:#"CustomView"
owner:nil
options:nil] objectAtIndex:0];
[cView.button1 addTarget:self action:#selector(actnForBtn1:) forControlEvents:UIControlEventTouchUpInside];
[cView.label1 setText:#"sometext"];
[self.view addSubview:cView];
And do add the method actnForBtn1:(id)sender in your view controller to do different things in different view controllers.
In View.h
+(View *)loadViewFromNib;
In View.m
+(View *)loadViewFromNib{
return (View *)[[[NSBundle mainBundle] loadNibNamed:#"View" owner:self options:0] objectAtIndex:0];
}
To load the View call
View *view = [View loadViewFromNib];
In your View.xib file set the Files Owner class to View and your Views class to View connect the Outlets only to the View, not to the FilesOwner!

Programmatically created UIViewController loading an Interface builder view.xib file

How to load an interface builder created view from a programmatically created UIViewController? I'm using Objective-C.
I was able to start with a reference project that did not use the interface builder, so I have no storyboard. I have successfully loaded views programmatically, but would like to be able to load some that were interface builder created.
More detail: I have 2 view controllers A and B. I'm currently in A. I click a button and in that button handler I load Viewcontroller B like this:
self.viewControllerB = [[ViewControllerB alloc] init];
[self.navigationController pushViewController:viewControllerB animated:YES]
I manually created a ViewB with a .m and .h. If I use an initWithFrame wherein i define a bunch of controls and lay them out programmatically, I can successfully call it as described above.
I add a new file to the project, which is a UIView which brings it up in the builder. Drop a TableView onto the view, and now I just want to see this load.
I named the xib ViewB.xib, I set the Class to ViewB like the pic below shows (In answer 1)
Whenever you need to load a view from a .xib use this:
First make a nib for the view in interface builder, and be sure to set its custom class to your view's class, see the picture:
and then load it in your code like this:
MyCustomNibView *myView;
NSArray *topLevelItems = [[NSBundle mainBundle] loadNibNamed:#"MyCustomNibView" owner:nil options:nil];
for (id view in topLevelItems) {
if ([view isKindOfClass:[MyCustomNibView class]]) {
myView = (MyCustomNibView *)view;
break;
}
}

Resources