Loading custom class UIView from NIB (IBOutlets nil) - ios

I'm trying to modularize a complex UI in several xib's.
I want to programaticly load each additional xib from file.
The xib has controls which are connected to the custom view code.
Then I try to load the xib the following way inside the main view controller:
WIFClientData *clientDataView;
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:#"WIFClientData" owner:self options: nil];
clientDataView = [nibViews objectAtIndex:0];
[clientDataView configure];
The problem is that when I try to configure the view:
-(void)configure
{
self.name.label.text = #"Name";
self.mobile.label.text = #"Mobile";
}
name and mobile are nil
I currently don't have File's owner connect, or set to any custom class. I only have the view which is layed in the xib, set to the custom class.
I have been reading a lot of things regarding to this but haven't found the answer yet.
Can someone help me?
Nuno

If you have a custom class WIFClientData and set a top-level view's class to WIFClientData in nib (which you then get via [nibViews objectAtIndex:0]), have IBOutlets connected to that view (not to file owner) then this should work. (works for me for custom cells)
Maybe you've misaligned something or mistyped?

Related

Utilizing IBOutlets/IBActions from external loaded Nib

Forgive me for my noob questions, but I really need some help. I am learning IOS development with swift2. Unfortuantely, the tutorials I've followed/done don't really get into much advanced stuff when it comes to working with Views/Nib files.
Anyhow, I am trying to create a custom class that will load my Nib and I can work with the Outlets/Actions of the newly instantiated class of type UIView.
I was able to find some information that got me to being able to load my view properly and insert it into my tableHeaderView, but I am kind of lost. I need a little guidance.
ReserveHeaderCell.swift
class ReserveHeaderCell : UIView{
#IBOutlet weak var ReserveHeaderImageView: UIImageView!
class func instanceFromNib() -> UIView {
return UINib(nibName: "ReserveHeaderCell", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! ReserveHeaderCell
}
}
I set the class in my xib to be this class, further, the outlet refers to a UIImageView within the parent view.
ReserveViewController.swift contains:
let reserveHeaderFrame: CGRect = CGRectMake(0,0,self.view.frame.size.width, 164)
let rhCell = ReserveHeaderCell.instanceFromNib()
rhCell.frame = reserveHeaderFrame
ReserveTableView.tableHeaderView = rhCell
And this all works. The frame gets created, the xib is loaded and added to the view. Great, the problem is, I don't have access to my IBOutlets that are defined in the ReserveHeaderCell.swift file. Also, I really don't know if this is the correct way to accomplish what I am trying to do.
What I am trying to accomplish (done with obj-C)
- (id)initWithFrame:(CGRect)frame {
if (self) {
NSArray *nib = [[NSBundle mainBundle]
loadNibNamed:#"HeaderNib"
owner:self
options:nil];
self = [nib objectAtIndex:0];
// ACTIONS GO HERE
}
return self;
}
That way I have access to any of the IBOutlets that are created (in obj-c the H file, but for my case, it would be the class, right?)
using the obj-c method, I can simply call view.outlet = "" and get access to them.
Any help is appreciated. Any links to tutorials that could help is appreciated.
Thank you in advance.
You can use this code to init your nib file
let view = (NSBundle.mainBundle().loadNibNamed("MenuHeader", owner: self, options: nil)[0] as? UIView)
tableView.tableHeaderView = view
Then your MenuHeader will be a normal .xib file with your cell inside it, just remember to adjust the constraints appropriately to fit on all the screens that you want. If you already have a class for your UIView you have to connect your nib file with this class and then you can use "view.label.text" and then change your values. Remember to keep a reference of this view or just create a new one when you have to change the header information. If you want to track an action the best way would be through a delegate method or using the NSNotificationCenter.

How to use xib file as custom view in storyboard

I use xib to create my custom view, and i bounded it with the same name .h .m file.
I set the custom view class to UIView's class in storyboard , but it didn't work.
my custom view
I drag a UIView
Step 1 :
Create a Xib (your View) file, then create your.h and .m files,
If you already have a viewcontroller that will use the xib: implements
everything in it.
Step 2 :
Open your Xib file, in the interface builder you will find on the left : File's owner, select it and then, on the right in the identity inspector tab, add your custom class.
Step 3 :
import your xib class in your.h file
Now you can create IBOUTLET in your.h file.
Step 4 :
To get the xib in your.m just write something like this -->
in viewDidLoad:(or everywhere you need it)
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"RunningMode_VC_Interface" owner:self options:nil];
runningViewXib = [subviewArray objectAtIndex:0];
runningViewXib.frame = self.view.frame;
[self.view addSubview:runningViewXib];
You will now add your custom view to your viewcontroller. Then create your custom interface/functionality methods to work easy on it.
hope it helps.

add a custom uiview with xib in my storyboard

I am using swift2.0 and I have just added a custom UIView called SortableTableTitleView:
and then I drag a UIView in my storyboard, and I changed the class of the view to SortableTableTitleView
When I tried to set the text of the label in the custom view, I just got a bad access error.
I tried to write the initwithcoder method of the view, but I don't know how I can load the element from xib. (It is somehow different with ObjectiveC). So, how can I solve this?
You cannot use xib files within the Storboard file. So either create the view fully in the Storyboard and use it as per normal. Or, add the view from your xib file add a subView to the view on the storyboard via code.
So something like this in the viewController:
UINib *nibFile = [UINib nibWithNibName:#"SortableTableTitleView" bundle:nil];
NSArray *views = [nibFile instantiateWithOwner:self options:nil];
UIView *sortableTableTitleView = views[0]; //Assuming it is the only view in the xib file
//Add it where you want as a normal view now:
[self.view addSubview: sortableTableTitleView];
I realise the code above is in objective-c - I'll get the Swift comparison when I get a gap (Being new to Swift and all)

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.

Resources