UITableViewController vs UIViewController - ios

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

Related

How to recreate UITableViewController with static cells support?

I have a lot of common logic, therefore all my viewControllers inherit from BaseViewController, BaseDetailsViewController or BaseWebViewController. The last two inherit from BaseViewController which inherits from UIViewController. The problem is I cannot use tableViews with static cells because my BaseDetailsViewController is not inheriting from UITableViewController.
I'v never used and inherited UITableViewController because the same could be achieved by inheriting from UIViewController, wiring it with an added UITableView and having implemented datasource and delegate methods. Therefore for the form type screens (SignUp or other data input screens), I use my own BaseDetailsViewController which adds nice and handy methods (input validation, custom styling, scrolling keyboard, handles input field navigation and etc.)
Using UITableViewController has two real benefits: 1) keyboard scrolling (if you use text fields) and 2) easy creation of your form UI elements inside on screen. The first benefit is irrelevant for me, because I'v already have my own implementation of this stuff inside BaseDetailsViewController. Regarding the second benefit, I'm creating my form inside scrollView which gives a lot of flexibility but it's a little bit more effort (especially when need to update the screen). Therefore I heard some guys implemented their own UITableViewController and then made it to inherit from their BaseViewController. Therefore I started to dig into this approach.
So far I'v came upon these two approaches:
Recreate your own tableVC. Not clear how to make it work for static cells. Currently my demo app crashes if my ReplaceTableViewController is not implementing numberOfRows and cellForRow, and not shows static cells if I implement them with dummy content.
method-swizzling. Not clear how to change class inheritance by injecting baseViewController inheritance for UITableViewController, thought still not clear which methods are needed to be added.
Anybody tried and want to share?
UPDATE I'm not using storyboards as I promote clean MVC - every screen as component should have its own Model, View (Xib), and controller, all stored in separate files to eliminate merge conflicts of multiple devs in large app projects (30+ screens). And therefore container view with embedded segue to tableViewController is also not an option.
UPDATE2 In case anybody would like to take a look why and how I'm doing this, here's a link to my open source template based new project generator framework which I started to publish recently.
Static cells need a UITableViewController. You can't changed this right now.
But to use static cells in a UITableView outside of a UITableViewController you can use a ContainerView in your Non-Table-UIViewController, where you place a real, separate created UITableViewController working with those static cells.
To share common code between multiple view controllers, inheritance is not that best solution as you found out by yourself while subclassing UIViewController vs. UITableViewController. You can use some sort of composition for sharing code or - especially for objective-c - categories.
Categories are not allowed to have its own properties, but there are workarounds possible with objc_setAssociatedObject.
Another approach would be to not use static cells, but dynamic cells in a UITableView with DataSource-Delegate :)
As you see in my screenshot, to reuse a special TableView with static cells, i place it in other ViewControllers in a ContainerView. Since you are not using storyboards, i am pretty sure that this can also be done by code without storyboard.

What class should I run async calls from?

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,

Best Practice: UIViewController or UIView

I am gonna design a component in IOS, in which we will have Table view and Grid View; means user can see his data in table or grid. So what i am doing is i added a UIViewController and added two child view controller one for table and another one for collection view. I am handling everything using UIViewController only. Its means when user wants to use my component he has to add as a child view controller only. My question is that "Is it the best practice to use UIViewController like i am doing or Should I convert everything to UIView because UIView is light weight." I am gonna write only presentation logic in my component. We will get data from outside using delegate. And if i should use UIView then when should i use UIViewController?
Thanks
Your current approach is correct.
UIViews should do one and only one thing: paint a view when asked to.
UIViewControllers are more complex. They are are responsible for setting up views with any data they need to do their job, compositing multiple views (or view controllers) together if needed, responding to events from view components or from the device in general, and communicating with the rest of the code/system.
Because your code wants to show two different kinds of information, it fits the UIViewController much better than the plain UIView style.
As you've pointed out, Apple themselves have many examples of UIView subclasses that have delegates and do complex things. However, if you're writing a new component and it is complex (as yours is), I seriously recommend going for the UIViewController approach.
A note on history: Apple used to be of the advice that UIViewControllers should only show/composit UIViews and not other UIViewControllers (even though, confusingly, they didn't always follow their own advice!). This would align with their making of some quite complex UIView subclasses. However, they changed this stance a while back, and added support to UIViewControllers for compositing other UIViewControllers' views inside them. If Apple's stance had always been as it is now, you might find that some of their UIView subclasses were implemented as UIViewControllers!
As an experiment, it would probably be quite educational to try and implement your component both ways. I predict that you'd find UIView approach more unwieldy, with you having manually re-plumb some of the 'wiring' that you'd get 'for free' with the UIViewController approach.
Avoid putting logic in UIView subclass.
As I think you can make grid view by using table view just simply add multiple views on each cells
at time of switching grid to list or list to grid simply check your type and reload tableview

iOS -- When to create a child ViewController vs. a UIView Subclass?

Maybe this is a silly question, but I've bumped into it a number of times during iOS Development.
Sometimes I'll develop a view component that I want to use on multiple screens, so I'll decide to subclass UIView and make it something I can use in multiple places.
Then, I start adding functionality to it. Maybe it needs to respond to an NSNotification, or it is supposed to respond to user touches.
At a certain point, I start wondering if I should really be making a UIViewController subclass, and add it to my UI as a child ViewController.
Is there any consensus on where to draw the line between adding some behaviors to a UIView, and when to create a full UIViewController?
I can't tell you about the consensus, but here's my opinion:
Subclass UIView only when...
You want to do custom drawing
You need to customize some behaviour of an already existing UIView subclass
You have special needs for layouting subviews. Most layouting can be done by UIViewController, though.
Maybe for special touch handling that you can't be done with gesture recognizers
Subclass UIViewController in all other cases. You almost always need a controller anyway, for writing glue code that ties together views and models, or for handling user interaction. Consequently, Apple has made it easy in UIKit to let controllers do all the work and to keep views as "stupid" as possible. For instance, it is very simple to nest controllers to create complex view hierarchies, without the need to have a single view subclass.
An indicator that subclassing UIView is not the first thing one should do is the section titled "Alternatives to Subclassing" in the UIView class reference. An indicator that subclassing UIViewController is the preferred thing to do is that there is no such section in the UIViewController class reference :-)
You should use a controller anytime that you need to handle or control data. Views are supposed to be as stupid as possible, not knowing what they are displaying but rather where. You can easily subclass and reuse ViewControllers. A good example, say you need to retrieve a string (or text) from the user throughout your app via a popover controller and a modal. Create a generic subclass of UIViewController that has a view with a textfield and a button. You can then use this view and it's controller in any capacity you need. Reusing it in the popover, modal or anywhere else (and generally passing the data back through delegation). Since you are dealing with data you should not being using a sole subclass of UIView.
From my experience I subclass UIViewControllers more often then UIViews. It is a little difficult for me to understand if you are solely talking about Containers or reuse of views in general application workflow. Either way though it should be the same.
I've used the embedded view controllers to load reusable table views from time to time. I've found that it's useful sometimes but not always. Communication between the two can be cumbersome, like if you want the embedded controller to communicate back up to the container. Delegation makes it easier but still cumbersome. It also limits you to iOS 6, if I remember right iOS 5 and lower don't support embedded controllers.
If it's just adding methods you can use a category to store some extra methods. I do that a lot on NSManagedObjects that I don't want to subclass and if I regenerate the NSManagedObject from the datamodel I don't lose the code in my categories. Gives me added functionality like calculated fields or conversion methods without having to subclass. If you don't need those methods for a particular instance just exclude the reference to the category.
Subclassing never is bad though IMO.

QuickDialog within frame

I'm trying to employ QuickDialog for an iOS 5 iPad app which uses storyboards, but I guess the question would broadly apply to UITableViewController as well.
My understanding is that when I'm initialising the QRootElement, the tableview that QDC creates will replace the view of my class, thus rendering ineffective anything I customise in the IB storyboard. I would like to be able to design the UI in IB, and have the QD table show up as a frame instead of taking over the whole screen.
I think the solution is to have the QuickDialog tableview set up as a subview of my UIView-based class. Is this correct? What would be the best way to achieve this? Would I have to rewrite the root initialiser in my custom view controller that inherits from QDC, or is there a different way, perhaps something like the approach used here?
Thanks!
I would recommend you inherit from the QuickDialogViewController as your main controller. The QDViewController inherits directly from UIViewController (instead of UITableViewController), so it's quite easy to just move the table view around and add controls around it.
If you really want to create everything from Interface Builder, your tableview will have to inherit from QuickdialogTableView, and you'll have to provide the delegate and data source yourself. Look at the QDViewController for that, as you'll have to write pretty much the same code.

Resources