Is this the correct "layout" for delegation? - ios

I'm building a simple calendar application based in a single view controller. The view controller has a hierarchy as follows:
CDViewController
CalendarView
EventView
AgendaView
TPKeyboardAvoidingTableView
EventInfoCell
My question specifically pertains to the EventInfoCell within my AgendaView. The Cell has various ways of laying out textFields and textViews, depending on the information that needs to be displayed. These textfields and textviews are enabled/editable based on the tableview's edit status and edit/delete core data objects. When the strings within these change, the cell needs to alert the managedObjectContext to save or delete an object, update the model within the agendaView that populates it's tableView, and update the model that pertains to all events for the calendar. My current configuration makes the viewController the delegate of EventInfoCell, but this complicates the update for the agendaView model. It seems almost counterproductive to set the EventInfoCell delegate to be the AgendaView, tell it when information changes, and then have the AgendaView pass the word on to it's delegate (the viewController), but if it is more compliant to MVC than bypassing the agendaView altogether, I will gladly implement it. I'm trying to figure out what is the better design pattern, any input is greatly appreciated.

"It seems almost counterproductive to set the EventInfoCell delegate to be the AgendaView, tell it when information changes, and then have the AgendaView pass the word on to it's delegate"
Why does this seem counterproductive? This is the way I would handle it. If you don't do it this way then you are going to have to open up some sort of properties or a notification or something in the AgendaView for the ViewController to pass the information back to it. That sounds more counterproductive to me than passing the information up the chain. Plus, you may eventually have some sort of changes in the EventInfoCell that require its delegate to act, but do not necessarily alter the Core Data model. So, I think you should pass the delegation up the chain.

Related

How can I recycle controllers in UICollectionView's cellForItemAtIndexPath?

I am displaying a number of cells, whose content is reasonably memory intensive. I have a custom controller that sets up a view to display the content, and updates the UI periodically. However, often UICollectionView asks for a particular cell several times. I want to know how to design (well) a system to re-use the controller + view if I have already created it for a given piece of data. I thought about storing a controller reference in the data object, but don't know if storing UI elements in what is meant to be data is a good idea. Also, if I did this, I would need to monitor retainCount on cell unload, and when it gets to '1', remove it from the data object, which seems a bit hacky. Similarly, a NSDictionary of data->controller pairs in the UICollectionView could also work, and would again require monitoring retainCount, or re-implementing a retain counting mechanism for my particular case. It's doable, but seems clunky.
I'm very new to ios, so it may be I'm approaching this all wrong. Any suggestions are greatly appreciated!
First of all, think if displaying a controller view inside a cell is a good idea. I'm not sure, but since i'm not familiar with your project, it's something only you can tell.
Secondly, You can create your own pool of controllers. When you need a controller to put inside the cell (in cellforIndexPath method), take one from the pool. If the pool is empty, create a new one. The cell shouldn't come with a controller of it's own, put it only in cellForItemMethod.

Data management across segues

This is a concept question.
Like many others, I have a parent scene and a child or detail scene. When I click on a specific button in my parent scene, prepare to segue gets called and I pass over a couple of properties. In my detail scene, I gather more information and need to save it for use by the parent. I have seen various methods involving delegates, using singletons, and passing directly back to the parent properties. Here is my question, would it be more correct to store the data in a database in the detail controller, or pass it back to the parent controller to store it? It seems to me that since it was collected in the child, it should be stored there.
Would that be the more correct way of handling it?
For simplicity, say the larger model is an array of custom objects and the detail view presents and edits one of those objects. If you pass a custom object to the detail vc on before the segue, there's no need to "pass it back" later. The parent vc passed that object in the first place, so we know it already has a pointer.
Instead, the parent vc should notice that the work has been done on the object it passed and react accordingly (usually update it's view) This can be done by one of a handful techniques:
just assume something changed and update the view on viewWillAppear
notice the custom object changed via KVO (observing one of its properties)
be notified that the object changed because the detail vc posts an NSNotification
learn that the object changed by arranging to be the delegate of the detail vc
pass the detail vc a block to execute when it updates the custom object
It's hard to say what's better without knowing more about your situation. I can say that simple is usually better, and that favors (1). I can also say that delegates are fine, but often overused.
If you're dealing with more than a few pieces of information, it would likely be much easier in the long run to use Core Data. If, down the road, you decided to add more functionality to the app, or wanted to store different kinds of information, it would take no more than a few extra lines of code to do this.
But from what it sounds like, you have a really simple app, so you should probably be fine just making an instance of your "parent scene" in your "detail scene" and storing whatever values you may have in the "detail scene" into properties that already exist in the "parent scene".
Does that answer your question well enough?

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.

Nil out NSFetchedResultsController Delegate when offscreen?

Is it best practice to Nil out NSFetchedResultsController Delegate when offscreen?
For example, I have a list managed by a NSFRC. When I tap a list item, I get a detail view. I can potentially change something on a detail view that will remove it from the list. Or, if I continue to slide through the detail views, I can cause it to load in more data (which would subsequently update the parent table view NSFRC).
I'm getting strange behavior when I DO nil it out. Can't seem to find advice on this anywhere.
No reason to nil out your NSFRC here. In fact, this is the main convenience of having your tableView managed by an NSFRC, is that it will update itself appropriately while you are off in other views changing data. This also applies data changes sequentially, rather than having to refetch all data when returning to your list.
I have posted a similar question time ago, looking for a technical explanation of this 'best practice'. However I didn't find anything.
I suppose that much of the suggested 'best practices' came from older iOS version, where viewDidUnload could have been called in case of memory warning, but that's not the case anymore.
In my experience, I found out that it is only mandatory to resign in case of background update and merge. All the other case depends on your application logic.
For example when you have nested CoreData entities with subsequent UIView, like so:
child1 (UITableView)-->child2 (Detail)-->child3 --> (UITableView)-->ecc...
Then, a change on child3 will have the child 1 table view react on that change, so you may want to avoid unnecessary call to a remote fetched controller, by resigning as delegate or introspecting the changement and returning YES or NO within the delegate method. It could be simpler and much efficient to refetch the query.
Keeping the same structure, suppose you have a mass update on latest UITableView by merging two context, if you have used the same context for all the controllers, then they will be trying to update its view even if not needed.
So for a simple case like UITableView-->UIView (detail) I can see no problem of keeping delegate assigned, all the other case, I would do a little analysis.

What is the appropriate design pattern for the following situation?

As an exercise I am working on a simple drawing app for the iPad.
I am using UISplitView, with the drawing view as the detail view. In the master view controller I present (in a table view) a list of the shapes drawn so far.
The user can edit or delete any shape from the master view controller, and also select and edit a shape by touching it in the detail view controller.
To notify each of the view controllers of the changes made by the other, I thought of using delegates, but I am not sure if this is the right pattern to use.
First, as I understand it, delegates are supposed to be used when a certain object encounters an event which they don't know how to handle. in that case they pass all the information to the delegate and let it handle the event. This is not the case here since both view controllers need to do something with the information. Using delegates here can cause code repetition.
Another reason I am thinking not to use delegates is that in the future I might want other view controllers to get the information of changes in the drawing. I can use multiple delegates (is it good practice in general?) but I'm not sure this is a good solution either.
Are there other solutions I should consider?
On the contrary, I think delegates might be the right pattern to use here - you don't necessarily delegate only when you can't handle an event (though that might be one situation where you would delegate).
Instead, consider delegates a way of getting information to or from another object, when you simply don't know what that object might be. For example, Apple uses the delegate pattern when working with UITableViews; in that delegate protocol, the table view knows perfectly well what to do in each situation, but still notifies your code when certain actions are about to happen. I think that's an excellent parallel for your situation. (Note that a parallel to your question's assumptions also exists, in the UITableView "data source," where the table view does require some bits of information.)
Another technology you could consider using, if you're really dead-set against delegates, would be to use notifications. You can have each controller subscribe to particular notifications, then have your shape (or detail view controller) post instances of NSNotification when observable changes happen. That way, you still get to handle events happening in a different controller, but without needing to maintain a delegate list.
As for code duplication, just consider refactoring as you start encountering situations where you would duplicate; maybe you should design a single delegate or notification subscriber object for the common code, then only do class-specific things in each of the other controllers?

Resources