Working principle of delegate and datasource - ios

Just want to know the working priciple of iOS delegate and datasource.
For example, when I call a [tableView numberOfRowsInSection] in some ViewController.
Seems that it is returning me [tableView.dataSource numberOfRowsInSection]
But how can I invoke [tableView numberOfRowsInSection] without returning [tableView.dataSource numberOfRowsInSection]?
May I know what is happening behind the code? Thank in advance.

In iOS, delegate and dataource are implemented as delegation pattern. The different between them is about it's responsible and relationship with the delegating object. delegate is control of user interface, while data source is control of data. They all have to adopt protocol, in which defines a set of methods that act relevantly with each others.
Table View delegate and data source implemented aim to adopt one of best practice of using delegation pattern. Delegation design pattern responds sometimes as a callback function, however, in the case of table view data source and delegate, it allows you to control and customize properties and behavior of table view.
An example of that you can see is that implementing delegate and data source allows you to customize your table view properties such as number or sections, number of rows, which type of cells and it's behavior like clicks a row.

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 differentiate iOS UIKit dataSource and delegate methods for multiple objects in the same UIViewController?

I noticed in using UITableView, UICollectionView, UIPickerView, UIScrollView, ..., and numerous other UIKit classes that the UIViewController containing the object instance often bears the role of DataSource and Delegate.
I understand from Apple's documentation what these data source and delegate methods are called, and how to implement them... for a single instance of each class.
My question is, how do you handle different instances in the same UIViewController? For example, if I have two UICollectionViews, or three UIPickerViews, ...., or fifty UIScrollViews? I can implement the data source method only once per UIViewController, but I somehow have to tell the program different instructions?
The only thing I can conceive is a gigantic switch statement or a bunch of cascading if-else if-else comparing the input to the delegate or data source method to each object instance in the UIViewController, which might get out of hand if there are many.
While we're used to using our view controller as the delegate, there's no need to do so. You can actually create NSObject subclasses that conform to the delegate protocol in question. You can then instantiate those objects and use them as the delegates of the UI objects (or whatever) as needed.
For example, consider a scene where I have two text fields, one which permits only numeric values, and one that does not accept numeric values. I can write a separate delegate object for each type of text field.
If implementing this programmatically, I would manually instantiate the two delegate objects, keep some strong references to them in my view controller, and then in viewDidLoad I can set each text field's delegate to be the appropriate delegate object.
If doing this in Interface Builder, you can actually drag an "Object" from the "Object Library" onto the scene (either in the bar above the scene or the document outline to the left of the scene):
You can then specify the class for this object:
Repeat this for all of your delegate objects:
And finally, you can go to your text field and specify the delegate by control dragging to the delegate object you added to the scene:
Doing it in Interface Builder means that it completely takes care of the instantiation of this delegate object for me and I have to do nothing in view controller's code.
Bottom line, if you want distinct behavior for a UI object, you can just instantiate a separate delegate object that manifests the desired behavior, and use that as the UI object's delegate. This pattern of instantiating separate delegate objects is common in iOS 7 custom transitions (where we have all sorts of delegate objects banging about), but can be used in this context, too.
BTW, you can obviously just subclass the UI control in question, too, and further encapsulate the logic there. That works equally well.
By creating referencing outlet for each controller,for example if you have two UITableView ,You can create outlet for each such as table1 and table2. To set number of rows in a section for these table ,you can code like follow
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == table1) {
return 10;
}
if (tableView == table2) {
return 5;
}
return 1;
}
You can create independent UIViews for each tableView or collection view with it's own .swift and .xib (and maybe if they are very similar you can reuse them). Doing that you will have the tableView and collecionView delegate methods in separated files and everything will be more clear. In your view controller you will just have to place the views, but you won't have any delegate methods there.
Well you are asking to differentiate the views with datasource & delegate in a smarter way. But you are overthinking this thing.
Everyone takes the different tableviews or pickers because they wan't be the same.
Otherwise they can be reused.
Now if they are going to be different from others then ultimately somewhere in your code you have to put the if...else or case statements. For example for tableview while setting the value of an UILabel or any value in your UITableViewCell.
If you are facing a such an issue that you have to put that many scrollviews or something in only one UIViewController then its an impossible situation if you are following the coding standards or may be your app design is faulty.

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.

Delegation and Data Source iOS

I have been learning about Delegation and Data Sources for iOS programming and need to ask, is there any differences that you need to do when you make a data source protocol than a delegate protocol?
Also how can I implement a delegate for many same objects in one delegate? Example one object with many unique custom alerts.
--Edit--
An example for the second part:
One object that has four different alerts each with different buttons. Since object needs to dictate how each button works by being a delegate for the alerts. How would I set the delegate methods to determine each alert?
Both types of objects more or less behave the same way, it is a matter of what they do that is the question.
A delegate type object responds to actions that another object takes. For example, the UITableViewDelegate protocol has methods such as didSelectRowAtIndexPath for performing actions upon a user selecting a particular row in a table.
Whereas a data source type object gives data to another object. For example again, the UITableViewDataSource protocol has methods such as cellForRowAtIndexPath and numberOfRowsInSection dictating what should be displayed in the table.
There is no hard difference between the two in terms of compilation, it is simply a coding style to make what objects do what very clear to the user of the code.
EDIT:
To answer your second question: if you want each alert to respond differently, you will need to write a different delegate for each alert. For example, if one of your alerts is a save confirmation alert (perhaps you are going to overwrite a file, and it pops up to confirm thats what the user would like to do), you would have an object such as:
#interface SaveConfirmAlertDelegate : NSObject<UIAlertViewDelegate>
#end
And in the #implementation for SaveConfirmAlertDelegate you would implement the proper save feature depending on which button the user pressed in the alert.
When you create an alert view, you specify what the delegate object should be, this does not have to be self. You could have your four delegates stored as different objects and set them on the alerts as necessary.
I hope this clears things up

Resources