Making a UIView outlet in Interface Builder - ios

I have almost lost what's left of my sanity today ladies and gentelmen. Interface Builder is about to take it away.
I am new in iOS dev and going through a book right now with all kinds of different tasks.
What I am trying to do is to call a view using a double tap. This isn't about gesture recognizer and the taps, it is purely about the outlet.
1) I have a xib file, where a small menu is drawn.
2) Upon a double tap gesture I want this menu to come out.
This is the way I got it working for me:
- (void)displayPanel:(UIGestureRecognizer *)gesture{
CGRect frame = CGRectMake(0, self.window.frame.size.height-100, self.window.frame.size.width, 90);
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:#"colorMenuView" owner:self options:nil];
UIView *colorView = [nibContents lastObject];
[colorView setFrame:frame];
[self.window addSubview:colorView];
[self.window setNeedsDisplay];
}
A nice little menu is drawn at the bottom.
But I want to do that not with the NSBundle's last object, I don't think it is a good approach. I want to do this by making an outlet connection to the UIView that holds my menu.
(I would've posted some pictures but I haven't got enough reputation yet)
When I try to make a connection I can't, the outlet isn't highlighting
When I change the Class of the View from UIView to CustomView I can connect the subviews, such as labels and buttons, which does seem to be how it should work. I still cannot connect the view though.
Now I add another standard view to the IB. And try to make a connection. It works! And if I try to connect the Custom View, it doesn't.
Now I change the Custom View back to standard. Neither of views can be connected.
Ok lets change one of the views to the Custom and connect another one. It works.
Let's do the implementation of another way of calling the menu now:
- (void)displayPanel:(UIGestureRecognizer *)gesture{
CGRect frame = CGRectMake(0, self.window.frame.size.height-100, self.window.frame.size.width, 90);
[[NSBundle mainBundle] loadNibNamed:#"colorMenuView" owner:self options:nil];
UIView *menu = self.menuView; // the outlet
self.menuView.frame = frame;
[self.window addSubview:menu];
[self.window setNeedsDisplay];
}
I have no errors for the chunk above. But the menu is still not shown. And it's nil, so it was never actually initiated.
Please help me to understand 2 things:
1) why IB does what it does?
2) why is the menu I finally got connected is nil?

In your second sample you set owner param of loadNibNamed to be self, but doesn't seem to have properly configured File's owner placeholder in the xib file. This results in nil outlet reference.
You should setup File's owner placeholder of colorMenuView xib to be an instance of specific class, eg. ColorMenuViewController (using Identity inspector). This will let you connect view outlet of used view controller with your top level view. This view can be then loaded using one of following approaches:
// 1
ColorMenuViewController* vc = [[ColorMenuViewController alloc] initWithNibName:#"colorMenuView" bundle:[NSBundle mainBundle]];
UIView* colorView = vc.view;
// 2
ColorMenuViewController* vc = [ColorMenuViewController new];
[[NSBundle mainBundle] loadNibNamed:#"colorMenuView" owner:vc options:nil];
UIView* colorView = vc.view;
Your base class, which implements gesture recognizer actions, can be used as the File's owner as well.

Related

Custom UIView subclass add nib subview

I have a custom UIView subclass let's call it CustomViewA which I init with initWithFrame: and add some UIViews programatically (like a UILabel and so on). Now there is need for another view to be added to CustomViewA so I created a nib which I lay out some GUI elements inside (one being a UISegmentedControl)
Now I'm having some issues on how to correctly add this nib as a subview to CustomViewA. Do I need to create .h/.m files for the nib? I want CustomViewA to receive the actions when the segmented control changes values.
[[NSBundle mainBundle] loadNibNamed:#"MyNibName" owner:self options:nil];
[self.view addSubview:self.nibView];
In the nib, make sure that the File Owner's class is set to the view controller you are adding it to.
You can add properties and IBActions like normal from the nib as well.
Do I need to create .h/.m files for the nib?
No, you needn't.
How to receive the actions when the segmented control changes values ?
You can set a tag number for segmented control in your xib, it should be unique in all the subviews of the view in your xib.
You can get the segmented control with the code. UISegmentedControl *segmentedControl = (UISegmentedControl *)[view viewWithTag:1024];, once you get the segmented control, you can add an action with the code [segmentedControl addTarget:self action:#selector(action:) forControlEvents:UIControlEventValueChanged];
Edit: How to get the root view of xib?
Use the code below:
UIView *rootView = [[[NSBundle mainBundle] loadNibNamed:#"YourXibName" owner:nil options:nil] firstObject];
I finally figured out what was happening. The nib that I added to CustomViewA was added outside CustomViewAs frame. So apparently when a subview is outside the superview's frame it will not intercept touches.

Load UIView with Nib and UIView class

I've tried this class
https://github.com/autresphere/ASDepthModal
i want it to popup like it does but i want to be able to set the labels programmatically, since i need the to change depending on what day it is.
I'm using storyboard, so i've created a .xib and uiview.h and uiview.m. In my main UIViewController i have:
xibContents = [[NSBundle mainBundle] loadNibNamed:#".xib" owner:self options:nil];
testView = [xibContents lastObject];
in my .xib i have set the file owner to my uiview class, this create a problem: NSUnknownKeyException
When i set the uiiew inside my .xib to my uiview class the application will load and i can open it just like it should, but i'm not able to change the state of the label programmatically? I'm complety lost here!
Typically speaking, UIViews do not have access to IBOutlets. Apple kind of intended xibs to only be assigned to UIViewControllers.
However, you can load a view from a xib in two ways:
1) Create an extra xib to use in your UIViewController. Set the File's Owner to your view controller, and the class name of the view to your custom view class. In interface builder, this is under "custom class". You can set the view as a IBOutlet, and iOS will create an instance of your custom class when your UIViewController loads the xib and sets itself as owner (like you tried above, but only from within a controller class)
2) Load a xib in a UIView class, and set self to the resultant object:
- (id)init {
self = [super initWithFrame:CGRectMake(0, 0, 1024, 352)];
if (self) {
NSArray* nib = [[NSBundle mainBundle] loadNibNamed:#"TCSNumberKeyPad" owner:self options:nil];
[[nib objectAtIndex:0] setFrame:CGRectMake(0, 0, 1024, 352)];
self = [nib objectAtIndex:0];
}
return self;
}
In either case, you will need to retrieve your label via code rather than IBOutlet properties. You can find your label in the subviews property:
UILabel* myLabel = [self.subviews objectAtIndex:0];
Actually got this to work. I took the wrong approach. I found it simpler to just create the view and populate it with background image and labels when the button got clicked. would have been simple to do it in a UI designer, but this wasn't that hard actually.
Thanks to the people who helped me :)
The file's owner should be the view controller, not the view itself. The view can have outlets to the labels. The view should be set to your custom class in your nib.

Single UIViewcontroller, how to switch among multiple xibs?

I have a subclass of UIViewController:
#interface KBViewController : UIViewController
with multiple xibs, for example, one is a Qwerty and the another is Dvorak layout:
KBViewControllerQuerty~iphone.xib
KBViewControllerDvorak~iphone.xib
So when the user click a button, Qwerty is switch to Dvorak. As you may see, the code logic is identical for both keyboard layouts. What I need is to reload the view with another xib.
Hopefully, all the buttons in the Dvorak xib will be hooks to the responding IBOutlets in KBViewController.
What is the right way to switch between the two xibs?
All Nibs has the designated File's Owner. IBOutlet and IBAction linking is done based upon the File's Owner. So you could define a view controller and two Nibs, with each Nib file's File's Owner set to the defined view controller.
That is, if you set File's Owner of all KBViewController*.xib files to KBViewController and have a KBViewController object somewhere you could load the KBViewController*.xib you want by initWithNibNamed method (recreate the view controller)
If you should maintain the same KBViewController object all along, you could create a KBViewController object without Nib. In KBViewController.m, implement loadView and manually load the UIView object with -[NSBundle loadNibNamed] method (load and change self.view programmatically).
UIView *someView = [[[NSBundle mainBundle] loadNibNamed:#"SomeNibFile"
owner:self
options:nil] objectAtIndex:0];
self.view = someView;
Note owner:self in above code. It must match with File's Owner of the #"SomeNibFile".
To change already loaded view:
id superview = self.view.superview;
[self.view removeFromSuperview];
UIView *someView = [[[NSBundle mainBundle] loadNibNamed:#"SomeNibFile"
owner:self
options:nil] objectAtIndex:0];
self.view = someView;
[superview addSubview:self.view];
More detailed explanation:
Resource Programming Guide - Loading Nib Files Programmatically
You can load your nib file manually and change the view attribute of your view controller or change any view you want, respectively.
UIView *someView = [[[NSBundle mainBundle] loadNibNamed:#"SomeNibFile"
owner:self
options:nil] objectAtIndex:0];
The objectAtIndex:0 is only correct when there is only one UIView root object in your nib file
After loading your view, you can set
self.view = someView;
Of course, if you have a subview in your view controller, then you can change that, too.

Custom UIView's labels not showing

I have custom UIView that has a xib file as well as .h and .m files. My custom view contains a number of UILabels.
I have added this view to a UIViewController's xib file by dragging in a UIView, going to the Identity Inspector and changing the class name to MyCustomView. MyCustomView is connected the the view controller with an IBOutlet property.
When the view controller is loaded, the MyCustomView's
- (id)initWithCoder:(NSCoder*)coder
method is called, but none of its labels show in the view controller's view. How can I fix this?
I already know how to add a custom UIView through code using:
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:#"MyCustomView"
owner:self
options:nil];
MyCustomView *view = [nibContents objectAtIndex:0];
[self.view addSubview:view];
but I want to know how to add through the xib file. I have searched for a while but haven't been able to find the answer, so if this is a duplicate please point me towards the correct answer.
Here are images of the custom view xib and the view controller xib:
I'm afraid You can not make UIViewController's xib load your own view's xib.
You'll either need to add those labels into you own view programly,
or
add the view into your viewcontroller's view programmly, as you showed in the code
I'd need to see more code to know for certain, but I suspect that the problem you are having is that the custom view (the parent of the UILabels) is not giving the UILabels dimensions. It's not calling -[UIView setFrame:]
To verify that, type this in the debugger:
po [[UIApplication sharedApplication] keyWindow] recursiveDescription]
That will print a description of the view hierarchy. Check what the frames of the UILbals are.

How to Add a Semi Transparent UIView to a UIViewController

Upon a certain user action, I wish to add to my UIViewController another UIView that will be half transparent; i.e. when it loads, the UIViewController view in the back will still be visible in the background, and the new UIView will appear as a layer above it.
The "Half Transparent" UIView should have several images and buttons in it, so I prefer to create a separated h, m and xib files for it so I can control it.
How should I do that?
Try this:
UIView *view = [[UIView alloc] init];
[view setAlpha:0.5];
[mainview addSubview:view]
Subclass UIView, create the nib file
Change the nib class to your custom subclass name
Change the file owner to become your view controller
In your view controller, declare a #property for the custom view using IBOutlet
Select the nib, drag from the file owner to the custom view and connect the outlet
In your button action, when you are ready to load the view, use
[[NSBundle mainBundle] loadNibNamed:#"NibName" owner:self options:nil];
Once this is done, your custom will be loaded from the nib and assigned to the property you declared.

Resources