A view knows how to interact with the user. It knows how to display some data, how to handle events, and how to give feedback to the user.
A view controller knows what but now how. It knows what data to display, and what to do in response to a user action.
A UIButton knows how to display a title and image, and how to track a click, but not what the title should be or what to do once clicked.
A UITableView knows how to display data in cells and how to handle editing, but it does not know what data to display or what to do when a cell is deleted. For that it uses a delegate and data source which will often be a view controller.
This division between what and how simplifies design and maintenance. You could make a subclass of tableview for every type of table logic, but then you cannot also control other views. A view controller can control several views and coordinate between them.
Edit:
So you should use a view controller any time you need to:
- coordinate between multiple views.
- coordinate between model data and views.
- respond to user interaction with a view.
- unload and reload views.
Note that a view controller is not strictly a UIViewController. You might have a view controller that is owned by a UIViewController and handles some views, but is derived from NSObject or whatever. The view controller manages some part of the view hierarchy rooted in the UIViewController and is owned by that UIViewController. The UIViewController can in turn be part of a hierarchy rooted at the application delegate and might be owned by a navigation, tab or other meta controller.
So the application delegate owns zero or more meta controllers such as UINavigationController. Each meta controller owns one or more UIViewControllers. Each of those owns a view hierarchy and may own several simple view controllers that help manage parts of the view hierarchy. If there is no need for a meta controller, then the application delegate could own or be a UIViewController.