How to properly subclass an existing row - ios

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.

Related

Static table cells with detail

I'm trying to make an iOS 'information' or 'guide' app in Swift. I wanted to utilise the Master Detail template so that when the user clicks a cell it will take them to a relevant ViewController with either basic text labels or a PDF file.
From what I understand, Dynamic Cells can be dynamically changed whilst the app runs however I want to set static cells from the storyboard (or programmatically) and their relevant content/PDF files so the user can view each one. I don't want any "new cell" or "editing" functionality.
How can I make this work? I would post my code so far but it's almost identical to the Master Detail template so I don't see any use. I know this is quite a vague question but I need help and don't know where to start.
Any help will be so appreciated!
A static table cell can entirely be created via storyboard. In the storyboard once you add a tableviewcpntroller you can prototype call added to it.You can add as many prototype cells to your table ( not necessarily every one should have common layout). After all cells are added you can assign individual tags to the cells if you need identify these cells from your code.You can add segue from each cells to move to different page.
Let me know if something more is needed.
In Interface Builder set the Content of the table view to Static Cells.
Drag as many table view cells as you need into the table view.
In the controller create IBOutlets for the labels and the other UI elements.
Connect the outlets in Interface Builder.
Rather than using the datasource methods assign the values directly to the UI elements via the outlets.

Adding a UIView based on a template in swift?

I've used UITableView before and like the way that the user can add a practically unlimited number of cells by entering information and the program uses a template. I'm wondering if there is a way to do this, but instead of using a table, using regular views or even buttons. For example, the user would tap a button, enter information, and return to the first ViewController and it would have a new view with the information in place of parts of a template that I designed.
Sorry if this is unclear. Basically I'm wondering if there is a way to make a table that is not as restrictive as a table, but uses several individual views in place of cells.
You can create re-usable views in the same way that you can create prototype cells.
Just right click in your project window, add new file and select User Interface > View. create it just like you would a prototype cell.
Then create a related class by adding a new swift file, link the two, create any outlets or actions you need and add any required logic.
Once you are done you can just load it wherever you need it, like so
self.headerView = NSBundle.mainBundle().loadNibNamed("HeaderView",owner:self,options:nil) as! HeaderView
You would likely need to pass in some required information, or setup the views frame or constraints.
I found a YouTube Video which should help guide you through the process. I've only skimmed through it so you may need to look around for a better one, but the general concept seems to be there.

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.

xlform custom rows using nibs

I want to use XLFormSelectorCell but I need to customize the UI in a nib file. How do I do this? Can I just create a subclass from XLFormSelectorCell instead of XLFormBaseCell or do I really need to rewrite all the methods in XLFormSelectorCell? Can you show me the best way to do it? Thanks!
It is clearly mentioned with example in this link.
All you need to do is just create a custom cell of type XLFormBaseCell and then manipulate the data according to your requirement
In the overridden +load method of your custom cell, you need to add your cell in the XLFormViewController.cellClassesForRowDescriptorTypes dictionary. But, when using nibs, instead of the class, you should use a string containing the nibName.
For example:
[XLFormViewController.cellClassesForRowDescriptorTypes setObject:#"nibName" forKey:#"XLFormRowDescriptorYourCustomType"]

One xib, several sub classes

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

Resources