iPhone: Which controller should handle the CRUD logic?
I'm building an app the works similar to the iPhone Notes app.
My app consist of two screens, first screen is a UITableView listing all the records. The second screen appears when you either click on one of the records or click an add button. This second view contains a UITextView where the user can add/edit the text for that record.
Both screens have a View Controller. The MyListViewController loads the records into the UITableView. When the user clicks on开发者_如何转开发 a record I create an instance of the MyEditViewController and push it using the pushViewController
method of the Navigation Controller.
MyListViewController -> MyEditViewController
My question is which controller should handle the CRUD logic, should it be the parent controller (i.e. MyListViewController) or the edit controller (i.e. MyEditViewController)?
One thing to note is that you should be able to delete a record from MyListController by swiping a table cell and selecting delete.
You can should also be able to delete from the MyEditViewController by clicking on a delete icon.
I'm basically trying to duplicate the Notes app but am unsure what is best practice in terms of where the CRUD logic should go.
In the scenario that you describe, the best pattern to use, would be the delegate pattern.
Simply make a delegate for your MyEditViewController and make it's delegate your MyListViewController.
You define a delegate as a protocol. So in your MyEditViewController.h
put in this:
@class MyEditViewController;
@protocol MyEditViewControllerDelegate <NSObject>
@required
- (void)myEditViewController:(MyEditViewController *)controller didSaveNote:(BOOL)save;
@end
and add this to your already existing MyEditViewController.h
code.
@interface MyEditViewController : UIViewController
....
@property (nonatomic, retain) id <MyEditViewControllerDelegate> delegate;
@end
In your MyEditViewController.m
code when you push weather the save or the cancel button you send the following message:
[self.delegate myEditViewController:self didSaveNote:YES]
or
[self.delegate myEditViewController:self didSaveNote:YES]
depending on you pushed save or cancel.
In your MyListViewController.h
you adopt your newly created protocol like this:
@interface MyListViewController : UIViewController <MyEditViewControllerDelegate>
and in your MyListViewController.m
you remember two things. First to implement the required delegate method:
@implementation MyListViewController
...
- (void)myEditViewController:(MyEditViewController *)controller didSaveNote:(BOOL)save
{
// Do business logic here depending on the value of save
}
and the last thing is setting your MyListViewController
to the delegate of your MyEditViewController
like this:
MyEditViewController *myEditViewController = [[MyEditViewController alloc] initWithNibNamed:@"MyEditViewController" bundle:nil];
[myEditViewController setDelegate:self];
That way you handle all CRUD logic in your MyListViewController
and that way you can update the Table View accordingly.
I have recently developed an application that has very similar requirements. I think you should be very clear about your Model, Views & Controllers.
Model is the non-UI part of your application, the management of Notes in your case. I created a singleton object, say NotesManager, whose shared instance can be accessed from anywhere in my code. Something like [NotesManager sharedInstance]
. In my application, the view controller does not read/enumerate the documents directory's contents (because thats not its job), the NotesManager does. The List view controller asks the notes manager for the notes to display. [[NotesManager sharedInstance] notesFromDocsDir]
;
Views are the UI part of your application. In this case, it would be the table view & the note's edit view.
Controllers are the ones that act as the link between your Views & Model. As you know, there is the ListViewController & the EditViewController.
Now, there are two types of interactions:
The first one originates from the UI & has to update the Model. For example, the user taps delete or save. In my application, i do something like [[NotesManager sharedInstance] deleteNote:Note]
. You can do this from both the View controllers.
The second one originates from the Model end & updates your UI. For example, in my application, I have enabled iTunesSharing
& hence a user can add/delete a note via iTunes. When such an event occurs, my UI has to update itself to reflect the current state of the documents directory. To accomplish this, the NotesManager dispatches an NSNotification
. The Controller(s) registers for these notifications & updates the view.
Now for your original question, the CRUD methods reside in the NotesManager. They can be called by the Controllers or by NotesManager itself, when it detects something has changed.
HTH,
Akshay
Both. And neither.
You should use a model to store/provide the data.
ViewController's should control the views and pass instruction to the model to save changes etc.
I would do the business logic in the model - simply call the methods in the model from the viewcontrollers.
Seeing as your child viewcontroller is doing the editing it should be that which instructs the model in that instance.
The parent viewcontroller should instruct the model when you handle the deletion of the data.
I'd say that a good solution is to implement all these operations in your Model. Say, you have a class called Note
that can handle CRUD operations. You will also need something like NoteCollection
that will provide valid data for your table view.
MyEditViewController will always deal with a single note that should handle operations like save and delete. These should update its state in your note collection.
精彩评论