2010/01/14

iPhone : CoreDataレシピ カスタムのプロトコルを作成する。

レシピのAddをpresentModalで行うときに、カスタムのプロトコルを作成して呼び出し元をそれに準拠させておく。

呼出し元クラス(カスタムのプロトコルに準拠)
やること:
1.プロトコルの設定
2.プロトコルメソッドの実装

呼出しクラス(カスタムのプロトコルを定義)
やること:
1.プロトコルの宣言
2.delegateの宣言
3.プロトコルメソッドの宣言



カスタムのプロトコルの使い方
呼出しクラス

やること:
1.プロトコルの宣言
2.delegateの宣言
3.プロトコルメソッドの宣言

  1. //プロトコルの宣言  
  2. @protocol RecipeAddDelegate;  
  3. @class Recipe;  
  4.   
  5. @interface RecipeAddViewController : UIViewController <uitextfielddelegate> {  
  6.     @private  
  7.         Recipe *recipe;  
  8.         UITextField *nameTextField;  
  9. //delegateを宣言  
  10.         id <recipeadddelegate> delegate;  
  11. }  
  12.   
  13. @property(nonatomic, retain) Recipe *recipe;  
  14. @property(nonatomic, retain) IBOutlet UITextField *nameTextField;  
  15. @property(nonatomic, assign) id <recipeadddelegate> delegate;  
  16.   
  17. - (void)save;  
  18. - (void)cancel;  
  19.   
  20. @end  
  21.   
  22.   
  23. //プロトコルのメソッドを定義  
  24. @protocol RecipeAddDelegate <nsobject>  
  25. // recipe == nil on cancel  
  26. - (void)recipeAddViewController:(RecipeAddViewController *)recipeAddViewController didAddRecipe:(Recipe *)recipe;  
  27.   
  28. @end  
  29.   
  30. </nsobject></recipeadddelegate></recipeadddelegate></uitextfielddelegate>  

実装部は長いのでいるとこだけ。
プロトコルメソッドを呼び出すだけ、実装はしなくてよい。実装はプロトコルに準拠した呼出しもとクラスで行う。
これでプロトコルを経由して呼出し元のメソッドを呼び出す。

  1. - (void)save {  
  2.       
  3.     recipe.name = nameTextField.text;  
  4.   
  5.  NSError *error = nil;  
  6.  if (![recipe.managedObjectContext save:&error]) {  
  7.   NSLog(@"Unresolved error %@, %@", error, [error userInfo]);  
  8.   abort();  
  9.  }    
  10.     //プロトコルを経由してメソッドを呼び出す。メソッドの実装は呼出し元で  
  11.  [self.delegate recipeAddViewController:self didAddRecipe:recipe];  
  12. }  




呼出し元

やること:
1.プロトコルの設定
2.プロトコルメソッドの実装

インターフェース
  1. #import "RecipeAddViewController.h"  
  2.   
  3. @class Recipe;  
  4. @class RecipeTableViewCell;  
  5.   
  6. @interface RecipeListTableViewController : UITableViewController <recipeadddelegate, nsfetchedresultscontrollerdelegate=""> {  
  7.     @private  
  8.         NSFetchedResultsController *fetchedResultsController;  
  9.         NSManagedObjectContext *managedObjectContext;  
  10. }  
  11.   
  12. @property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;  
  13. @property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;  
  14.   
  15. - (void)showRecipe:(Recipe *)recipe animated:(BOOL)animated;  
  16. - (void)configureCell:(RecipeTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;  
  17.   
  18. @end  
  19. </recipeadddelegate,>  

実装部
プロトコルのメソッドを実装する。

  1. #pragma mark -  
  2. #pragma mark Recipe support  
  3.   
  4. - (void)add:(id)sender {  
  5. //ここは呼出しメソッド。ここから呼出しクラスを起動してdelegateする。  
  6.     RecipeAddViewController *addController = [[RecipeAddViewController alloc] initWithNibName:@"RecipeAddView" bundle:nil];  
  7.     addController.delegate = self;  
  8.    
  9.  Recipe *newRecipe = [NSEntityDescription insertNewObjectForEntityForName:@"Recipe" inManagedObjectContext:self.managedObjectContext];  
  10.  addController.recipe = newRecipe;  
  11.   
  12.     UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addController];  
  13.     [self presentModalViewController:navigationController animated:YES];  
  14.       
  15.     [navigationController release];  
  16.     [addController release];  
  17. }  
  18.   
  19. //プロトコル実装部 dismissModalViewControllerでモーダルを除去する。  
  20. - (void)recipeAddViewController:(RecipeAddViewController *)recipeAddViewController didAddRecipe:(Recipe *)recipe {  
  21.     if (recipe) {          
  22.         // Show the recipe in a new view controller  
  23.         [self showRecipe:recipe animated:NO];  
  24.     }  
  25.       
  26.     // Dismiss the modal add recipe view controller  
  27.     [self dismissModalViewControllerAnimated:YES];  
  28. }  
  29.   
  30.   
  31. - (void)showRecipe:(Recipe *)recipe animated:(BOOL)animated {  
  32.     // Create a detail view controller, set the recipe, then push it.  
  33.     RecipeDetailViewController *detailViewController = [[RecipeDetailViewController alloc] initWithStyle:UITableViewStyleGrouped];  
  34.     detailViewController.recipe = recipe;  
  35.       
  36.     [self.navigationController pushViewController:detailViewController animated:animated];  
  37.     [detailViewController release];  
  38. }