Communicating between UIViewController and UITableViewDelegate - ios

I have a UIViewController which contains a UITableView (amongst other views).
The UITableView could get its cells from one of two UITableDataSource, depending on some condition.
My UITableDataSource class also acts as my UITableViewDelegate.
When a cell is selected (tableView:didSelectRowAtIndexPath) I may want to perform an action on the UIViewController, such as performSegue or show an alert.
What would be the best way to do this?
Add a weak reference to the UIViewController inside each datasource/delegate class
Create a delegate per datasource/delegate class which calls functions inside my UIViewController
Your suggestion here!
I considered making my UIViewController the UITableViewDelegate but as the cells are different depending on the source I thought it would get messy.
Note: I say "best way" but really I am just interested in alternate approaches

The most common approach is to subclass UITableViewController and implement UITableViewDelegate and UITableDataSource there. You can return whichever cell you require in cellForRowAtIndexPathbased on any state in your controller class.

Related

How to link Table dataSource and delegate outlets to UITableViewController?

I'm new to Swift/iOS development.
I have a UITableView in my storyboard that I want to populate with some data. In my attempt to do so, I created a class that inherits from UITableViewController. The implementation is not yet complete, but my understanding is that by inheriting from this class I can provide an IBOutlet to both dataSource and delegate.
When I try to drag the outlet into the source file, I don't get the insertion point that I got when I tested this before. See image below:
What do I have to do to define this class as the handler for the UITableView?
Set your viewController to inherit from UIViewController, not from UITableViewController (It seems like your IB is set up like that).
Do not forget to set your class to ZeroconfTableController on the interface builder.
Than, you will be able to set the delegate and datasource. NOTE: the delegate and the datasource will not create IBOutlets.
Assign the delegate and the dataSource the following way:
Also make sure, your viewController conforms to the protocols.
class ZeroconfTableController: UIViewController, UITableViewDataSource, UITableViewDelegate {
In your storyboard, select the UITableView and change this to the name of your UITableViewController subclass. You then do not need to do any linking stuff.
If you're using your own UITableView, inherit from UIViewController, not UITableViewController.
If however, you want to use a UITableViewController (which personally I don't use) in your storyboard, then do inherit from UITableViewController. In this case you won't have to wire up the UITableViewDataSource nor the UITableViewDelegate.

CollectionViewController, should I subclass or implement its delegate/datasource with a normal UIViewController?

When I am implementing a viewController with CollectionView, whether should I drag drop a CollectionViewController from storyBoard then creating a MyCollectionViewController class, which is a subclass of CollectionViewController?
OR should I just use a normal viewController, add a collection view to it,and implement its dataSource and delegate protocol?
I know one of the advantage for later is that you may have multiple CollectionViews under one ViewController? But what other pros and cons?
And how it applies to the TableViewController, as they are quite similar to each other.
UICollectionViewController inherits from UIViewController, so it essentially is a UIViewController with a UICollectionView and some built-in functionality. Per the documentation, this functionality is:
If the collection view controller has an assigned nib file or was
loaded from a storyboard, it loads its view from the corresponding nib
file or storyboard. If you create the collection view controller
programmatically, it automatically creates a new unconfigured
collection view object, which you can access using the collectionView
property.
When loading a collection view from a storyboard or nib file, the data
source and delegate objects for the collection view are obtained from
the nib file. If a data source or delegate is not specified, the
collection view controller assigns itself to the unspecified role.
When the collection view is about to appear for the first time, the
collection view controller reloads the collection view data. It also
clears the current selection every time the view is displayed. You can
change this behavior by setting the value of the
clearsSelectionOnViewWillAppear property to NO.
I prefer to always subclass UIViewController and add a UICollectionView in storyboard. This means that my subclass has to implement the UICollectionViewDataSource and UICollectionViewDelegate protocols and I have to set them in storyboard, and I have to make sure that when the view controller appears that I reload the collection view. But because I implement the behavior myself, it feels like I have more control. If you tend to use the regular, default behavior, then perhaps go with the UICollectionViewController to save time.
I feel exactly the same way about UITableViewController and UIViewController with a UITableView - I prefer the latter for exactly the same reason.
If you are sure that your UI will have only CollectionView, use CollectionViewController.
This rule applies for tableViews also.
Personally I started to follow a different approach in general. I use plain UIViewController to wich I add UITableView or UICollectionView. In the controller I only create a IBOutlet for the view.
class MyViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
}
Next I create a separate object as my datasource
class MyDataSource: NSObject, UITableViewDataSource {
init(with tableView: UITableView){
//Register cells, configure tableview, etc
}
numberOf...
cellForRowAt...
}
Then in my view controller, i have a lazy var with the datasource:
lazy var dataSource: MyDataSource = { return MyDataSource(with: self.tableView) }()
And finally in viewDidLoad I set the datasource to the tableview:
tableView.dataSource = dataSource
By doing this, you can keep your viewcontroller really clean and small as it should be. You prevent the MVC (massive view controller) problem and follow the principle of single responsibilities. Also your datasource is now reusable across multiple view controllers.

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

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.

Will a UIViewController subclass also affect my UITableViewControllers?

I need to add a common method to all my view controllers no matter what type they are. I notice though that some of my viewcontrollers inherit from UIViewController and some from UITableViewControllers.
How do I write a subclass that can be used for both?
UITableViewController inherits from UIViewController, so if you want to be able to call your custom method from both, you can write a category on UIViewController and then call methods from that category in any subclass of either UIViewController or UITableViewController. Here's a link to Apple's docs on categories and extensions. http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html
if you add a category to UIViewController, you will be able to call those methods on UITableViewController subclasses, as UITableViewController is a subclass of UIViewController

Resources