iOS - What is the difference between Table View and Table View Controller - ios

In the Object Library of Xcode, there are two options one can use to create table view - table view and table view controller.
What is the difference between the two and when would they be used ?

A TableViewController is a ViewController with a TableView built in. This will have the delegate methods needed already declared and setup. This VC is already a TableView delegate and datasource. It cannot be resized. Upside is ease of use, downside is very limited flexibility.
A TableView is just that a TableView (subclass of UIView). It can be added to a ViewController and resized, used alongside another view based object, etc. The upside is the flexibility, the downside is that you have to setup the delegate and datasource methods yourself (in my opinion, well worth the time to get the flexibility).
One other note is that when using the new Static TableView cells (part of iOS5), you have to use a TableViewController.

The UITableViewController is a subclass of the UIViewController. It already assumes you will have UITableView as your rootView, so you already have access from the code to a tableView (self.tableView). It implements the UITableViewDataSource and the UITableViewDelegate protocol. It also gives you alot of methods for you to override. It allows you to not depend on XIB file, because you already know what you will have (UITableView as a rootView).
The UITableView is just UIView, normally you will have to comply to the protocols I have referenced above in your UIViewController in order to populate (data source) and work with it (delegate), and you probably have to create an IBOutlet for your UITableView.
On one hand you have speed but you are not as flexible as the other path. On the other you have the opposite.

Related

tableView delegate and datasource

I'm learning Swift. Sometimes I see that Main.Storyboard is used to set up the tableView delegate and dataSource (ctrl+click and so on). Sometimes I see that it's done through coding instead like so:
// create the variable for the tableview
IBOutlet weak var someTableView : UITableView!
// setup delegate and datasource
sefl.someTableView.delegate = self
self.someTableView.datasource = self
I do understand how it works with second way. But it's difficult to realize how it works through Main.Storyboard with no IBOutlet setup.
Thank you for your responses!
It works exactly the same way :)
Let me refresh the principle:
You have a class, provided by Apple in this case, that has to work for a lot of scenario. Apple decided to use a kind of inversion of control, called delegation, where the workflow is inverted (hence the name) : instead of the view controller giving order to the tableView by calling methods on it, it is the tableView that goes and fetch its orders from the controller by calling methods on it.
In order to achieve this kind of IoC (inversion of control), the TableView MUST know the "address" of the object it has to ask for its order. Like you have to know your boss' email address to ask him stuff. So, the UITableView class as a property called dataSource that means to store that address.
Now as a ViewController programmer, you have to set this property to be the address of the view controller that will give the order to that tableview.
2 ways of doing it :
in code : in the view controller, you have a property pointing to the tableview (if linked from the storyboard, it is called indeed an IBOutlet, but doesn't have to be) and you set it's delegate property to self. (meaning 'hey tableView, your boss is myself)
Or you do it in the storyboard, because the graphic template for the tableView let you ctrl+drag from the tableView to the ViewController and set the datasource connection. In this case it will be the storyboard who will have to find the address of the tableView (since it is the one creating it, it's kinda easy) and setting it's delegate property to be the address of the view controller (meaning hey tableView, your boss will be this guy)
Either way, the viewController has to be ready to answer all the question from the TableView, so conforming to the UITableViewDataSource protocol.
the delegate scenario is the same.
It is important to understand how the loading of views works in iOS. Your xib will be translated into the hierarchy of views and they are loaded onto the memory. When you make an IBOutlet of those views, you'll have a reference of that loaded view in your code. If you do not create an IBOutlet, it doesn't mean that the view isn't there. It is there and it is in the memory.
When you set the delegate and the dataSource of a tableView and when the tableView is loaded onto the memory, it sets the delegate and the dataSource of the loaded tableView to the class as specified by you. It doesn't matter if you do not have a reference to it.

UITableViewController in UINavigationController to represent tree structure of unknown depth

I am pretty new to iOS. I have some data that is essentially a tree structure which is fetched from an external database so its depth is not defined at compile time for the app. I would like to display this information using UITableViewControllers inside of a UINavigationController. At this stage, I have embedded a UITableViewController in a UINavigationController in my storyboard, and have written a subclass of UITableViewController to display the first level of the tree. How do I programmatically segue to a new instance of the subclass of UITableViewController that I have created while also creating references for prototype cells I have defined in the storyboard. Is it possible to set up this kind of structure in iOS with UITableViewControllers and a UINavigationController?
Any help would be much appreciated.
Thanks!
In your TableView delegate, put some code into the didSelectRowAtIndexPath: method to create a new instance of your tableViewController subclass. Either pass it whatever data it needs to populate its cells, or possibly use your top level TableView delegate/datasource as the delegate/datasource for every new instance (you will have to keep track of where in your data hierarchy). You can then use self.navigationController pushViewController:animated: to transition to the new tableViewController. If you use the same subclass at each level, the cellForRowAtIndexPath: method will use the same cell reuse identifier (unless you code otherwise), so your prototype cells should be used at every level.

Can a property of a UITableView be the UITableView Delegate and DataSource

I have a custom view that's a bit of a hack. Basically it's a UIView with tableView as it's property, with additional views in the tableView that need their own delegates. I need a viewController for the UITableView and can't make the UIView it's delegate according to this SO link Custom UIView as UITableView delegate and datasource?.
Can I make the UITableView have a property of UIViewController and set that UIViewController as the tableView's delegate?
In this case according to OOP, the UITableView has a UIViewController so technically, I could expect this to work. But, I am wondering if down the line somewhere this could create problems since the UITableView and UIViewController are coupled in this way.
You don't need a UIViewController for the UITableView - you just need an object or objects that implement the data source and a delegate protocols. As per the accepted answer on the question you linked to you can use a separate controller class to provide this.
The right answer depends a little on how the table is used with your UIView subclass.
If the table will always have the same content (Say a list of months) and there is no value in exposing or abstracting the properties then you can code the delegate and dataSource inside your UIView subclass or in an assistant class.
If the table content will vary depending on how the UIView is used (say a list of people where you don't know what the list is - friends, relatives, employees...) then it would make sense to simply expose the tableview's datasource (and delegate if necessary) properties via your UIView subclass

What is the difference between UIViewController and UITableViewController

Sometimes I want to subclass UIViewController for some app wide customizations. Eg. something that all view controllers should perform during viewDidLoad or viewWillAppear or so.
Naturally I subclass UIViewController and go from there and all view controllers inherit from that. But some of the controllers run tables. And there is UITableViewController designed for that purpose.
So I subclass UITableViewController too and just do the same things there. Which does not seem to be the smartest thing in OOP terms. And there is no multiple inheritance etc.
And as UITableViewController inherits from UIViewController ...
Now I am asking myself why I don't just create my own table view controller that inherits from my very own view controller subclass and adds all the table stuff. But what is "all the table stuff"?
There is the skeleton code that xcode adds to every new table view controller. Quite handy but that can be easily moved to code snippets.
There is the declaration of the protocols UITableViewDelegate and UITableViewDataSource. Easy going. The implementation of those methods has to follow in each subclass of UITableViewController anyway.
There are probably reasonable default implementations of all those mandatory methods in the protocol. Such as returning 0 for numberOfSectionsInTableView: or nil for titleForHeaderInSection or 44.0f for heightForRowAtIndexPath: (Bad example though. Could be smarter not implementing that at all)
So despite the obvious stuff, are there any miracles that UITableViewController takes care of?
I believe all of the behavior UITableViewController adds is well defined in the class documentation: https://developer.apple.com/documentation/uikit/uitableviewcontroller?language=objc
The UITableViewController class creates a controller object that manages a table view. It implements the following behavior:
• If a nib file is specified via the initWithNibName:bundle: method (which is declared by the superclass UIViewController), UITableViewController loads the table view archived in the nib file. Otherwise, it creates an unconfigured UITableView object with the correct dimensions and autoresize mask. You can access this view through the tableView property.
• If a nib file containing the table view is loaded, the data source and delegate become those objects defined in the nib file (if any). If no nib file is specified or if the nib file defines no data source or delegate, UITableViewController sets the data source and the delegate of the table view to self.
• When the table view is about to appear the first time it’s loaded, the table-view controller reloads the table view’s data. It also clears its selection (with or without animation, depending on the request) every time the table view is displayed. The UITableViewController class implements this in the superclass method viewWillAppear:. You can disable this behavior by changing the value in the clearsSelectionOnViewWillAppear property.
• When the table view has appeared, the controller flashes the table view’s scroll indicators. The UITableViewController class implements this in the superclass method viewDidAppear:.
• It implements the superclass method setEditing:animated: so that if a user taps an Edit|Done button in the navigation bar, the controller toggles the edit mode of the table.
All of these are behaviors which should be easy to re-implement if they apply to your specific controller and table view.
In general I have found it preferable to implement these behaviors myself in order to allow for alternate inheritance hierarchies as you noted and because I usually consider setting both the delagate and datasource of a table view to be a view controller a design smell. Those are independent concerns which usually can and should be handled by some other class (e.g. a dedicated data source for a particular model class) rather than bloating a view controller.
So despite the obvious stuff, are there any miracles that UITableViewController takes care of?
Not that I am aware of. As far as I know UITableViewController is mostly a convenience class that can be replaced with your own subclass that adds a few lines of code.
Apple's class documentation pretty much says all that UITableViewController does (and I'm not repeating that here because it may well change in the future). Sometimes, additional information can be gleaned from a class' header file, but in the case of UITableViewController.h the source code comments just repeat what is already in the class docs.
In the end you must decide yourself what you want to replicate in your own subclass. Maybe your project does not need .nib handling? Or none of your table views is editable? So just don't code that...
It seems that the UITableViewController takes care of a lot of management issues that really you could just do for yourself, if you wanted to. Check out the documentation -- it will automatically create a UITableView for you, reload it, etc.

Subclass UITableView with Custom UITableViewCells

What I have: 10+ view controllers using a UITableView with custom UITableViewCell. Each view controllers load different data and forward to different sub-pages, thus they cannot combine together.
The aim of the change is to centralize the management of table view's look & feel in a single custom UITableView subclass. But since the data loaded by each view controller is different, I think the UITableViewDataSource and UITableViewDelegate have to be assigned to its original view controller class.
How do I make the change? Or I am thinking at wrong direction?
A tableview's datasource can be separate and independent from its delegate. So, put all of your appearance configurations in a UITableView subclass that implements its own delegate methods, and then create a separate NSObject subclass for each tableview that is responsible for the datasource implementation.
You could make a superclass for all your view controllers that collects all the common logic.

Resources