In my iOS app I have a view controller and a UITableView subclass on one of my views. Currently the UITableView manages it's own data (creating connections, and being the delegate which handles the callbacks).
I was wondering if this is best practice? Is it better to run this on the view controller and then pass the data into the table? Does this not matter at all?
Please explain the reasons in addition to answering my question.
Thanks!
It would be more standard to implement the delegate and dataSource methods in the ViewController.
It is quite unusual to subclass the UI*View classes, except to customise drawing. UITableViewCell is a bit of an exception to this rule.
If you find your ViewController getting a bit big you might think about implementing the delegate and dataSource in a separate class.
In addition to mcfedr's answer, views are things that interact with user and it is generally good to separate concepts (unless unavoidable). Also note that historic versions of ios (iirc) view controllers may load/unload views on demand, so any application logic in there may cease to exist.
In this scenario, I generally have only one class... The UIViewController instance that contains the following view hierarchy:
view -> myTableView
With this approach, my UIViewController will:
Have an IBOutlet to a UITableView (myTableView)
Implement methods of UITableViewDelegate
Implement methods of UITableViewDatasource
Set myTableVIew.delegate to self
Set myTableView.datasource to self
When the host UIViewController is the delegate and datasource of your UIViewContoller, all code can exist in one class. This keeps the code of your project tighter but does tightly couple your logic.
The alternative approach would be to subclass UITableView and implement UITableViewDelegate and UITableViewDatasource. This will be a desirable approach if:
You wanted to reuse the UITableView in multiple UIViewController
You wanted to encapsulate the UITableView logic from the UIViewController
Here is the thought process I use:
Am I going to reuse this UITableView and its logic?
Yes -> UIViewController class and UITableView subclass
No -> UIViewController class only
The best practice would depend on the number of programmers involved, the repeatability of the UITableView, coding patterns already established. This is often a matter of preference and I hope my answer shed some light on why you would go either way,
Related
I have a UIViewController in my application that contains a UITableView. This tableView has a few different states for section 2. The rows in this section can vary by height, cell type and number of cells.
The way I used to handle this was one UIViewController with lots of different if-statements in the UITableViewDelegate and UITableViewDataSource. Now, after a while, this has given me quite a lengthy and complicated controller.
I thought about two possible routes to fix this. The first one would be different UITableViewDelegate and UITableViewDataSource classes, based on an if-statement. The other would be to load in a different UITableViewController for each of the possible states.
What do you guys think would be the cleanest solution? Or are there any other cleaner solutions?
Firstly create an extension for viewcontroller which confirms to tableView dataSource and delegate protocols.
To achieve this we can create a custom method in presenter class to handle all this code and call this method whenever required.
My app uses the Stanford course's CoreDataTableViewController, which is a subclass of UITableViewController.
For particular views of my app I create subclasses of CoreDataTableViewController to manage a particular view.
I've just recently hooked up state encode and restoration throughout most of my app and it all seems to be working ok. The only thing I've left late is implementing the UIDataSourceModelAssociation protocol to allegedly preserve visible and selected rows of UITableViews (I was also hoping it may preserve the editing state of the table view, and of a particular row if I've selected it to delete, but haven't confirmed yet).
I implemented the UIDataSourceModelAssociation within CoreDataTableViewController hoping that it would just then work for all my views, but on debugging it the feature doesn't work, and adding breakpoints I see that neither of the two UIDataSourceModelAssociation methods are ever called when i put my app into the background with the home button, or restore it cold by re-running in XCode.
CoreDataTableViewController and my subclasses of it implement some dataSource methods to actually display the rows in my table view. I've searched around and found that UITableViewController automatically adds itself as the dataSource for the tableView.
I've added sanity asserts in my subclasses viewDidLoad functions of the form
assert(self.tableView);
assert(self.tableView.dataSource == self); <--- fails here
Which fails on checking the dataSource being ourselves. I can see by logging and using the debugger that the dataSource is non-nil at this point.
I guess I just wondered whether when we subclass a class does each class share the same self value, or is it because my UITableViewController has set itself to be the dataSource, but by the time I've subclassed it twice down to my particular view instance it's self is slightly different than the parent UITableViewController. Or is something else intercepting the dataSource and forwarding on as required. As a fix should I consider hardcoding my own subclass to self, or have the CoreDataTableViewController add itself as the dataSource explicitly as this is where the UIDataSourceModelAssociation methods are implemented.
For reference my view hierarchy consists of my UITableViewController subclassed views living inside NavigationControllers which I've heard may cause issues.
Just a little of clarity on how subclassing should work with respect to self pointers across the classes and wondering if anyone could figure out why my protocol methods aren't being called would be really appreciated.
Cheers
I'm still not sure why my tableViewController's dataSource isn't directly set to self. But clearly my dataSource methods are called as my tableView functions. Obviously some sort of object is forwarding on dataSource methods to my actual class for me...
In the end getting the UIDataSourceModelAssociation protocol methods to be called was as simple as ensuring that both the UITableViewController and the UITableView within it had restoration ids.. with just the outer UITableViewController having a restoration id, none of these methods are called.
Sadly now I'm scuppered by these methods being called before my UIManagedDocument has finished loading so I cannot actually do anything useful within them. That's another problem though.
What all does UITableViewController get me that makes it actually useful? Is there any bonus is using it instead of just using a UIViewController for views with UITableViews in them? I ask because I want my views with UITableViews to inherit from a base view controller (which inherits from UIViewController). If I use a UITableViewController then having a base class for all my views becomes more difficult.
Not much. It provides some conveniences, but you never really need it; I often don't use it.
The main things, aside from the automatic setup when you create one in the storyboard, are the three properties tableView, clearsSelectionOnViewWillAppear, and refreshControl. But they don't do anything you can't do yourself.
Well I do think both Retro and matt's answer are correct, from personal experience it is much easier and less "hackY" to use UITableViewController with UIRefreshControl, then trying to get UIRefreshControl work with UIViewController with a UITableView.
Nothing more then the boilerplate code ready for setting the data source and connection to your tableView object, some getters and setter to make your life easy if you not want to put your effort to do the same thing which is available.
But in your case for SubClass its not fit to have UItableViewController
According to the Model-View-Controller pattern, applied heavily in Cocoa Touch, UIViewControllers should always handle the logic behind how a concrete UIView in the scene behaves.
I am curious as to how Apple implements it's UITableView class while keeping in line with this philosophy. Especially since UITableView inherits from UIScrollView and UIView in turn.
When you add a UITableView to one of your classes, does it have a UIViewController handling the way it behaves in the background? I know that a UITableViewDelegate is in charge of telling the table how many rows it should have, etc. But what about it's inner workings?
I'm gonna take a wild shot here, because I'm not sure I really follow your question. When you add a UITableView, you HAVE to have a controller associated to it to control how it handles and renders. Either a UITableViewController or a UIViewController that implements UITableViewDelegate and UITableViewDatasource. If you don't there's no way you can control what it does.
I have a MainViewController, and I want to add two UITableView's to it, each with different cells. But I don't want to clog up my MainViewController code by checking in the table delegate methods which table it is, and then acting on it. It gets too messy.
So I thought I would subclass UITableView and let it handle the cellForRow and other table methods by itself, and this way when I want to add a table to MainViewController, all I'd have to is
CustomTable *customTable = [[CustomTable alloc] init];
[self.view addSubview:customTable];
and all the delegate methods would be handled in that class, leaving my MainViewController clutter free.
Am I approaching this wrong? Should I be subclassing UITableViewController instead? What's the difference?
When to subclasss UITableView? Not now.
Create two classes, which are member variables of your view controller. Point the table view delegates at each of your two new classes.
In Cocoa you tend to combine classes rather than inherit from them as you usually do in Java and C#.
In 3 years of professional working as a objective-c programmer, I didn't need to subclass UITableView once, the patterns, cocoa is depending on, — MVC and delegations (with using protocols), are just simple yet strong enough. And populating a tableview is just one of the best examples.
Make sure, you understand all this topics, as otherwise you will find yourself fighting the framework constantly.