Does it ever make sense to split UITableDelegate and UITableDataSource? - ios

This has bugged me for a long time. There are two delegate protocols defined for UITableView: the actual delegate and the data source. However, given the way the methods are distributed between the two, I'm yet to see a situation when it is practical to implement the protocols in two separate objects. Could anyone give me an example when it actually makes sense to do so?

Short answer: Yes it does.
Long answer:
They are split in 2 different protocols, because they serve different purposes.
The delegate is responsible for managing aspects of the table itself like selection, reordering and deletion of rows, ... UITableViewDelegate Protocol Reference
In contrast to that UITableViewDatasource is responsible for adapting your data model so that it fits the needs of the table. It provides the cells for the table, tells the table how many sections there are, how many rows per section there are, ... UITableViewDatasource Protocol Reference
Depending on your data and what you want to do with the table, that code can become arbitrarily large. If it's getting too large, you can split it up for better navigation and overview. That would be one case I can think of where this distinction can improve code quality.

IMO you don't get any benefits by doing so, as the datasource just provides methods to interact with data, same as the delegate. If your store is big and clumsy, separating the datasource won't solve the issue.
No added value
You can get some unpredictable behavior when forcing the separation:
UITableView issue when using separate delegate/dataSource
How to avoid big and clumsy UITableViewController on iOS?
It depends on the specifics of the app
On the other hand, depending on the app design it may be required to separate the datasource from the delegate:
Lighter View Controllers
UITableView delegate and datasource in a separate class after parsing

Related

Why is tableView:canMoveRowAtIndexPath: in the UITableViewDataSource protocol?

Why is tableView:canMoveRowAtIndexPath: is UITableViewDataSource protocol and not in UITableViewDelegate protocol?
Similar methods (e.g. tableView:canFocusRowAtIndexPath:) are in Delegate protocol. I don't think it's a mistake, so can anyone explain why such method is part of the data source and not the delegate?
A general explanation of which methods belong to data source protocols and which belong to delegate protocols is also appreciated.
The delegate methods generally have to do with the appearance of the table view.
The data source methods generally have to do with the content of the table view. It's often the case that the displayed content's order is fixed. Say the table view was displaying stops on a bus line, or the chapter headings of a book. You can't let the user reorder those: it isn't something that the content itself supports.
Notice that both delegate and data source are actually involved in the decision as to whether a row can move. The data source gets the method you named, but the delegate gets asked tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: at the same time.
The UITableViewDatasource protocol documentation:
The UITableViewDataSource protocol is adopted by an object that
mediates the application’s data model for a UITableView object. The
data source provides the table-view object with the information it
needs to construct and modify a table view.
As a representative of the data model, the data source supplies
minimal information about the table view’s appearance. The table-view
object’s delegate—an object adopting the UITableViewDelegate
protocol—provides that information.
The required methods of the protocol provide the cells to be displayed
by the table-view as well as inform the UITableView object about the
number of sections and the number of rows in each section. The data
source may implement optional methods to configure various aspects of
the table view and to insert, delete, and reorder rows.
Hope, that clears things out.
EDIT: With my own words (but repeating the docs): Datasource declares methods those somehow directly or indirectly affect/reflect the data model, whereas the method tableView:canFocusRowAtIndexPath: can't be said similar to tableView:canMoveRowAtIndexPath: because it has nothing to do with the data. That said, datasource carries constructive character, delegate - informative.

How to structure my code

I have a UIPageViewController that contains two "pages" of UITableViewControllers. These UITableViewControllers need to be filled with JSON data from the internet. However, this UIPageViewController needs to be reused in many places within my app meaning that the data that the UITableViewControllers use changes.
My question is: how should I structure my code so that I can easily change the data that the UITableViewControllers access? Should I pass the data to the initialised UIPageViewController so that it can pass it on to the UITableViewControllers, or is there a better way to do this?
Thank you!
This is quite a broad question, and there are potentially many different approaches. Which one is best is arguable and not really inferable from the information available.
If you have UITableViewControllers that are simply displaying downloaded JSON data, then you might want to have a dedicated class that deals simply with downloading the data. E.g. MyJSONDownloader.
This class might have a method like - (NSArray *)getLatestData that returns the latest things you want to display in a table.
Then in your UITableViewController subclasses you want to call this method and display the data accordingly.
I'm assuming from your statement:
These UITableViewControllers need to be filled with JSON data from the internet. However, this UIPageViewController needs to be reused in many places within my app meaning that the data that the UITableViewControllers use changes.
that you will be downloading data frequently from the web and that this data is constantly changing. (If not then change your question.)

Best way to implement UICollectionViewDataSource protocol?

I have theoretical question.
Currently my app is using UICollectionView as a way to display objects list. UIViewController, that contains UICollectionView as subview, implements UICollectionViewDelegate protocol and acts as delegate and datasource. Datasource uses NSFetchedResultsController to provide data;
In my opinion this is not the best way to implement datasource, and implementing it in separate class looks way better idea. But the issue it that datasource depends on search parameters in UITextField, and some other buttons selections, so every time when user types text into search field or press the any of "sorting" buttons I should update datasource (in particular fetchRequest in NSFetchedResultsController).
So, finally, my question: Is there any "best practices" of implementing datasources that depends on external parameters? Should I create separate class for datasource of leave it the way it is now? If implementing datasource as separate class - should I create datasourcedelegate for calling self-made delegate methods on delegate when datasource was updated or there is some other workarounds for this problem (I'm not considering using notifications on datasource update because as for me notifications mechanism is more global solution then I need here)?
I'm not looking for the fastest way, I just want to find out the rightest theoretical way of implementation.
Thank you all in advance :)
I personally implemented a concrete NSObject derived class, that implements UICollectionViewDataSource as well as NSFetchedResultsControllerDelegate that practically translates the fetched results controller events (object inserted, updated, deleted) to collection view events (insert, update or delete cells). You can find examples on how to do this, I took mine from here but I implemented it as a separate class instead of a category over collection view. I found my class highly reusable, in practice I use it in all of my projects where there is a need to visualize managed objects in a collection view. A similar class can be implemented also for UITableViewDataSource.
If you need to update the fetch request with the search predicate, I would subclass your newly created DataSource class, and add the logic to update the fetch request right there. Say, you add a -(void)updateSearchFilterWithText:(NSString*)text method where you add the logic to update the fetch request of the fetched results controller. Don't forget to perform fetch again afterwards and call a reloadData on the collection view!
With this architecture the view controller owns this dataSource object. Every time the user updates one of your filtering text field (or other widget), the view controller calls the updateSearchFilterWithText: of your data source object and the rest of the work is done by this later.
What you currently have is the standard approach. While there is no defined 'best' approach, what you describe is certainly a better approach.
Your view controller would own an instance of your new data source class, and would itself most likely handle the delegate methods (because these are actions to take rather than data to provide), so when anything changes in the UI the view controller should be 'pushing' these changes to the data source. No additional delegation should be required.
You shouldn't be creating your data source with the idea that text fields and buttons are directly driving changes in. Your data source should be presenting a generic interface where you can update the fetch request to execute (which covers the predicate and sorting) and change how the cell is configured (perhaps with a block). This way you keep your business logic in the view controller and the reusable data source code in another class that is reusable for other collection views / projects.

What is best practice when it comes to reusable UITableViewCell's and delegates?

I'm building an app that presents table views in a majority of the screens. They present a handful of different table view cells, but there is one that is presented in 3/5 of the table views. This cell, which displays a video and provides an interface for users to interact with the video (like, comment, flag, delete, play/pause, etc), has a fairly large delegate with seven methods/functions.
My question is:
Would it be a best practice to set up a separate controller that would be a property of my view controller to be assigned as the delegate to the cell, or to subclass a UITableViewController with the methods already implemented?
The problems I see with the latter is that I would then have to implement a weird way to handle the data source (set up methods to return the models, always ensure that videos are stored in that array) and the former just seems a little odd to the standard MVC practice. Any advice?
Update
I began factoring out a data source to use that implements the cell's protocol. Another issue that I seem to be running into is displaying multiple cells, i.e.:
I have a searchDisplayController that displays UserCell's and VideoCell's, based on the selectedScopeIndex of the search bar. One way I could handle this is to create a dataSource for this tableView that handles both cases, or swap out data sources based on changes to the selectedScopeIndex. Are either of the two options looked down upon? Is swapping a table view's data source valid?
I solved this issue by implementing a UITableViewDataSource controller that would also handle the cell's delegates. I was able to shorten the 7 method delegate to a 3 method delegate on the data source, used to push new controllers, remove objects from the data model, and handle fading/updates.
Granted, I needed to pass reference to the UITableView, the UIView, and the UIStoryboard of the source UIViewController, but the code is much more readable and manageable.

List of Items vs. Data Source

When building a view for an iPhone app, one must consider how variable data will be determined by the view. Two design options jump readily to mind:
An NSArray of items
A dataSource property, which implements a protocol and returns the items.
The former is used by views such as UITabBar, while the latter is used by UITableView. What are the pros and cons of these options? Is there a reason for the two distinct paradigms, or is one universally superior?
It's mostly about the amount of data and limited amount of memory in relation to simplicity.
Simpler is always better if you can get away with it. A tab bar probably have less than 10 items which is no problem to hold in memory at once so the simplest solution is the best.
A table view however may have thousands of rows that may contain expensive data like images. Therefor it has a more complex design to be able to keep only the necessary data in memory.

Resources