One xib, several sub classes - ios

I have one xib file for a custom UIView subclass. Works fine. I'm able to load the correct nib and create an instance of my class and it contains all the subviews I added to the xib file.
However, I have also subclassed this view, but I can't figure out how to create an instance of this class and get it to use the xib file used by the parent class. Is this even possible? I don't want to create a new xib file for my subclass, since the view hierarchy, subviews and GUI looks the same, it's just the code that differs.
Can I load a nib and "connect" it to another class than the one specified as the "Custom class" in the xib settings? Or can I create a new instance of a view and tell it to use a xib of a certain name?

You can try to write something really weird with -awakeAfterUsingCoder: to substitute created object, but this is really shaky and a few can get it right.
The thing is that .xib file stores set of serialised objects, when this set is loaded, information about each object, i.e. it's class, size, other attributes, parent object, constraints are as well deserialised and applied. So, xib files store which class should receive +alloc and other messages and, consequently, which objects will then receive all the attributes via KVC (-setValue:forKey:). So, no, you can't just configure some class to load some xib, because xib file tells which class should be loaded.
As a soulution I'd suggest to refactor your code, (for example) incapsulate different subclasses logic to some other object. So, before you had multiple subclasses with different logic, then, you'll have single class, loadable from xib, but you have to set some MyDifferentLogicVariant1Implamentor entity to preserve different logic for 'different' classes.
Superclass - Subclass1 - Subclass2
vs
Superclass.differentLogic = DifferentLogicImplementor1
Superclass.differentLogic = DifferentLogicImplementor2

Related

How to properly subclass an existing row

I'm needing help in correctly subclassing an existing row so I can change the UI only, not the function. The type of row I'd like to subclass is TextRow.
Again, I only want to change the UI and not the functionality.
Eurek mentions here a way to do it but I can't seem to figure out the correct way to do it. I'd like to form rows look like this.
The steps according to Eureka:
Subclassing cells using the same row
Sometimes we want to change the UI look of one of our rows but without changing the row type and all the logic associated to one row. There is currently one way to do this if you are using cells that are instantiated from nib files. Currently, none of Eureka's core rows are instantiated from nib files but some of the custom rows in EurekaCommunity are, in particular the PostalAddressRow which was moved there.
What you have to do is:
Create a nib file containing the cell you want to create.
Then set the class of the cell to be the existing cell you want to modify (if you want to change something more apart from pure UI then you should subclass that cell). Make sure the module of that class is correctly set
Connect the outlets to your class
Tell your row to use the new nib file. This is done by setting the cellProvider variable to use this nib. You should do this in the initialiser, either in each concrete instantiation or using the defaultRowInitializer. For example:
<<< PostalAddressRow() {
$0.cellProvider = CellProvider(nibName: "CustomNib", bundle: Bundle.main)
}
You could also create a new row for this. In that case try to inherit from the same superclass as the row you want to change to inherit its logic.
There are some things to consider when you do this:
If you want to see an example have a look at the PostalAddressRow or the CreditCardRow which have use a custom nib file in their examples.
If you get an error saying Unknown class <YOUR_CLASS_NAME> in Interface Builder file, it might be that you have to instantiate that new type somewhere in your code to load it in the runtime. Calling let t = YourClass.self helped in my case.
Basically what I need help with is setting up the correct xib/nib and class to use within the form. Thank you.

What exactly does a nib file look like if you were to look inside?

I'm just learning about nibs and swift and am curious about something. I know that if you have a main.storyboard file, that a nib is loaded first fir the root view controller, then for any views that may exist hierarchically under that view controller, however... I'm wondering something.
When they say a nib is 'loaded' does that mean that, a single function CALLS instances of the ui objects that you would like to load, based on the storyboard that you have built in the interface builder?
If not, what is the right way of looking at this? I'm trying to collect an easy to understand, accurate mental model of what happens.
Thanks!
What exactly does a nib file look like if you were to look inside?
Go right ahead and look inside and see! It's just an XML file; perfectly readable by a human.
I know that if you have a main.storyboard file, that a nib is loaded first fir the root view controller, then for any views that may exist hierarchically under that view controller
Correct! To be more precise, think of every "scene" in the storyboard as comprising two nibs, one containing the view controller, the other containing its view, the view's subviews, and everything else constituting that scene.
When they say a nib is 'loaded' does that mean that, a single function CALLS instances of the ui objects that you would like to load, based on the storyboard that you have built in the interface builder?
Think a nib as just a bunch of potential object instances. Loading the nib turns those potential objects into actual instances. Loading a nib is thus just another way of instantiating and configuring objects. A nib being "loaded" simply means that the nib is read and the objects it describes are instantiated and retrieved. That is why you can load the same nib multiple times to get multiple instances of those objects.

Creating and Using Custom UITableViewCell Template in Storyboard

I have a UITableView where I'd like to have multiple types of UITableViewCells. The different types of cells have a lot of similar properties, but have a few key differences, so I was hoping to create a template UITableViewCell class (TemplateCell) that the different cell types could extend.
I've tried doing this by creating a the TemplateCell class and having an associated .xib file. I then tried to go to my UITableView storyboard file and created my various cell types that subclassed my template. However, when I added those cell types to the storyboard file, they showed up as blank and didn't have any of the properties I had in the template file.
Is there an better way to create UITableViewCell templates?
You can create a TemplateCell class and separate classes for every other Cell (inherited from TemplateCell). Then you could assign common IBOutlets of EVERY subclassed cell to it TemplateCell class. Or you could operate with them by looking for the views with specific tags if you don't want to bother with outlets for base class.
Unfortunately you can't draw views in IB respecting some base view, so you should draw each cell separately, but you can use common outlets declared in the base class, and those outlets (properties) that differ, put into inherited cell classes.
Without 3d-parties IB doesn't support loading views from xib to a storyboard or another xib. You can use XXNibBridge for that.

One xib, multiple classes without inheritance in iOS?

I have two classes and one xib. I can't simply use one parent class which will be linked with this xib because it means multiple classes (and of course it is not acceptable for me to insert an object of one parent class into the object/class of the another one).
So is it possible to link multiple classes with one xib if they have the same IBOutlet variables but fully different classes?
No, Its not possible to assign multiple classes to one single XIB.
Instead create multiple UIView & load it on one single XIB controller

Query a nib file for frames, layout data

I have a UIView subclass that instantiates itself from a nib file. Prior to that, I would like the superview to be able to ask the custom view what frame it's going to need/want.
Currently I have a class method on the custom view that I update by hand when the frame of the custom view in the nib is changed in IB. Ideally I would like a class method that peeks in the nib and reports back directly from the nib.
How can I peek into a nib file and retrieve information from it? Should I load it as NSData and parse the XML or is there something a little less brutal?
If an instance method will work, you should be able to use the -sizeThatFits: method.
If it definitely needs to be a class method, you can write your own class method that is very similar to -sizeThatFits: where you take the CGSize param that is passed in and calculate the appropriate size for the view.
You're not specifically getting data from the nib, you're getting data from the associated class.

Resources