1

これは非常に簡単な解決策です。私はリンゴiphoneCoreDataRecipesの例を使用しています。私はレシピ(RecipeListTableViewController)のタ​​イプのリストを持つ次のテーブルビューにレシピタイプ(すなわち、飲料、デザート、エントリー)の初期テーブル(RecipeTypeTableViewController)からドリルダウンしようとしています。私は新しいRecipeTypeクラスを作成し、これを使って選択したRecipeTypeのレシピを返すことができると考えました。これまで私が得ることができる最良の選択肢は、すべてのレシピの同じリストを表示しています。元のコードは、NSFetchedResultsを使用してすべてのレシピを表示するRecipeListTableViewControllerで始まります。今、私はRecipeTypesの最初のビューを持っていますが、選択したタイプをRecipeListTableViewControllerに渡す方法がわかりません。選択したRecipeTypeのリストを表示するためにRecipeListTableViewControllerを変更する必要がありますが、これを実装する方法がわかりません。私は基本的にはfetchedresultsのNSMutableArrayを別のテーブルビューに渡したいが、どちらの方向を取るべきかはわからないと思う。そして、私はRecipeListTableViewControllerの他の作業アクション、つまりレシピの検索と編集を台無しにしたくありません。これまでのテーブルアクションのイメージは次のとおりです[RecipeTypeTableView] [1] & [RecipeListTableview] [2]。ご提案いただきありがとうございます。 RecipeType.hNSFetchedResultsドリルダウンを準備する方法対象cを持つ別のテーブルビューに

ファイル:RecipeType.m

私はレシピの種類の初期ビューを作成するために私のレシピクラスNSManagedObjectからNSManagedObject *タイプを使用する(前菜、ベヴこれら

ファイルを削除した

など)RecipeTypeTableViewControllerに -

ファイル:Recipe.h

@interface Recipe : NSManagedObject 
@property (nonatomic, strong) NSManagedObject *type; 

ファイル:RecipeTypeTableViewController.h

// RecipeTypeTableViewController.h 
// Recipes 
#import <UIKit/UIKit.h> 
@interface RecipeTypeTableViewController : UITableViewController <NSFetchedResultsControllerDelegate> 
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; 
@property (nonatomic, strong) NSManagedObject *type; 
@end 

ファイル:RecipeTypeTableViewController.m - セグエ一部

#import "RecipeTypeTableViewController.h" 
#import "Recipe.h" 
#import "RecipeListTableViewController.h" 
@interface RecipeTypeTableViewController() <NSFetchedResultsControllerDelegate> 
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; 
@end 

@implementation RecipeTypeTableViewController 

static NSString *MyIdentifier = @"showRecipes"; 

- (void)viewDidLoad { 
[super viewDidLoad]; 
// register this class for our cell to this table view under the specified identifier 'ARecipeType' 
self.title = @"Category"; 
//[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"ARecipeType"]; 

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangePreferredContentSize:)name:UIContentSizeCategoryDidChangeNotification object:nil]; 
// Uncomment the following line to preserve selection between presentations. 
// self.clearsSelectionOnViewWillAppear = NO; 

// Uncomment the following line to display an Edit button in the navigation bar for this view controller. 
// self.navigationItem.rightBarButtonItem = self.editButtonItem; 
NSError *error = nil; 
if (![[self fetchedResultsController] performFetch:&error]) { 

    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    //abort(); 
} 
} 

- (void)viewWillAppear:(BOOL)animated { 

[super viewWillAppear:animated]; 
self.title = @"Category"; 

} 

- (void)didChangePreferredContentSize:(NSNotification *)notification 
{ 
[self.tableView reloadData]; 
} 

- (void)didReceiveMemoryWarning { 
[super didReceiveMemoryWarning]; 
// Dispose of any resources that can be recreated. 
} 

- (void)dealloc 
{ 
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIContentSizeCategoryDidChangeNotification object:nil]; 
} 
#pragma mark - Table view data source 

//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
//#warning Incomplete implementation, return the number of sections 
//return [[self.recipeTypeFetchedResultsController sections] count]; 

// return 1; 
//} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
// Number of rows is the number of recipe types 
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; 
return [sectionInfo numberOfObjects]; 
//return self.recipeTypes.count; 
} 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ARecipeType" forIndexPath:indexPath]; 

// Configure the cell 
NSManagedObject *recipeType = [self.recipeTypes objectAtIndex:indexPath.row]; 
cell.textLabel.text = [recipeType valueForKey:@"name"]; 
return cell; 
} 

#pragma mark - Fetched results controller 

- (NSFetchedResultsController *)fetchedResultsController { 

// Set up the fetched results controller if needed. 
if (_fetchedResultsController == nil) { 
    // Create the fetch request for the entity. 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"RecipeType" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 
    NSLog(@"Setting up a Fetched Results Controller for the Entity named %@", entity); 

    // Edit the sort key as appropriate. 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 

    // Edit the section name key path and cache name if appropriate. 
    // nil for section name key path means "no sections". 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Recipe"]; 
    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 


    NSError *error = nil; 
    if (![self.fetchedResultsController performFetch:&error]) 
    { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    } 
} 

return _fetchedResultsController; 
} 

#pragma mark - Navigation 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
if ([[segue identifier] isEqualToString:@"showRecipes"]) { 
    NSLog(@"Setting RecipeType for the RecipeListTableViewController"); 
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
    Recipe *selectedType = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    RecipeListTableViewController *recipeListViewController = segue.destinationViewController; 
    recipeListViewController.type = selectedType; 
    recipeListViewController.managedObjectContext = self.managedObjectContext; 
} 
} 

ファイルの準備:RecipeListTableViewController.h - NSPredicate部とFRCキャッシュ

#import <UIKit/UIKit.h> 
#import "RecipeAddViewController.h" 

@interface RecipeListTableViewController : UITableViewController <RecipeAddDelegate, NSFetchedResultsControllerDelegate> 

@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; 
@property (nonatomic, strong) NSManagedObject *type; 

ファイル:RecipeListTableViewController.m

#import "RecipeListTableViewController.h" 
#import "RecipeDetailViewController.h" 
#import "Recipe.h" 
#import "RecipeTableViewCell.h" 
#import "Recipe+Extensions.h" 
#import "TypeSelectionViewController.h" 
#import "IngredientDetailViewController.h" 
#import "Ingredient.h" 
#import "WhereViewController.h" 
#import "FavoriteListTableViewController.h" 
#import "RecipeTypeTableViewController.h" 
#import "RecipeType.h" 


@interface RecipeListTableViewController() <NSFetchedResultsControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating> 

@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; 
@property (nonatomic, strong) NSArray *filteredList; 
@property (nonatomic, strong) NSFetchRequest *searchFetchRequest; 
@property (nonatomic, strong) UISearchController *searchController; 

typedef NS_ENUM(NSInteger, RecipesSearchScope) 
{ 
searchScopeRecipe = 0, 
searchScopeIngredients = 1 
}; 


@end 

@implementation RecipeListTableViewController 


#pragma mark - Fetched results controller 

- (NSFetchedResultsController *)fetchedResultsController { 

// Set up the fetched results controller if needed. 
if (_fetchedResultsController == nil) { 
    // Create the fetch request for the entity. 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Recipe" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

[NSFetchedResultsController deleteCacheWithName:@"Recipe"]; 

    // Create predicate 
    //if (self.type) { 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type == %@", self.type]; 
    [fetchRequest setPredicate:predicate]; 
    //} 


    // Edit the sort key as appropriate. 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 

    // Edit the section name key path and cache name if appropriate. 
    // nil for section name key path means "no sections". 
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Recipe"]; 
    aFetchedResultsController.delegate = self; 
    self.fetchedResultsController = aFetchedResultsController; 

    NSError *error = nil; 
    if (![self.fetchedResultsController performFetch:&error]) 
    { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    } 
} 

return _fetchedResultsController; 
} 

/

私はFRCキャッシュを「レシピ」に設定しています。それはクラッシュします。これは、キャッシュCoreDataを見るためのこの手掛かりを示しました:致命的なエラー:セクション情報の永続キャッシュが現在の設定と一致しません。あなたは不正にNSFetchedResultsControllerのフェッチ要求、その述語、またはそのソートの説明を変更しました。

キャッシュをnilに設定するか、[NSFetchedResultsController deleteCacheWithName:@ "Recipe"]を追加します。述語集合の前には、物事は期待通りに機能する。私はinitalビューコントローラと2番目のビューコントローラにこのキャッシュを持っています。たぶんそれは問題です - 私は最初のビューコントローラでキャッシュが必要ですか?

答えて

0

まず、データモデルは少し洗練されている必要があります。それぞれのRecipeTypeにはおそらく多くの関連したRecipesがある可能性があります。したがって、RecipeTypeからRecipeまでの関係は、から多くのになるはずです。あなたはデータモデルエディタでこれを変更し、モデルクラスを再生成する場合は、その後、次のようになりますRecipeTypeクラスを持っている必要があります。

@class Recipe; 

@interface RecipeType : NSManagedObject 
// not sure what purpose this property serves; it might now be superfluous... 
@property (nonatomic, strong) NSManagedObject *type; 

@property (nonatomic, strong) NSString *name; 
@property (nonatomic, strong) NSSet<Recipe *> *recipes; 

@end 

私は時間ごとRecipeがに属することができるということであるために仮定します1つだけRecipeType。だから、RecipeからRecipeTypeに逆の関係は、一対一であるべきであり、Recipeクラスがゆえの特性を持っています:

*property (nonatomic, strong) RecipeType *type; 

次に、あなたはあなたのRecipeListTableViewControllerはに関連しているだけRecipesを表示したいです関連性RecipeType。これを達成するには、取り出した結果コントローラーに述部を追加する必要があります。 fetchedResultsController方法では、追加:

if (self.recipeType) { 
    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"type == %@", self.recipeType]; 
} 

(あなたはまた、同様に、関連するRecipeTypeに検索を制限するために検索を修正する必要があります)。 RecipeTypeTableViewContollerでは、あなたのprepareForSegueニーズが唯一の正しいRecipeTypeを渡す:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {  
    if ([[segue identifier] isEqualToString:@"showRecipes"]) { 
     NSLog(@"Setting RecipeType for the RecipeListTableViewController"); 
     NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
     RecipeType *selectedType = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
     RecipeListTableViewController *recipeListViewController = segue.destinationViewController; 
     recipeListViewController.recipeType = selectedType; 
     recipeListViewController.managedObjectContext = self.managedObjectContext; 
    } 
} 

新しいRecipeを追加するたびに、あなたは正しいRecipeTypeに割り当てる必要があります。だから、RecipeListViewControllerに関係を設定するために、あなたのprepareForSegueを修正:

... 
else if ([segue.identifier isEqualToString:kAddRecipeSegueID]) { 
    // add a recipe 
    // 
    Recipe *newRecipe = [NSEntityDescription insertNewObjectForEntityForName:@"Recipe" inManagedObjectContext:self.managedObjectContext]; 
    newRecipe.type = self.recipeType; 

    UINavigationController *navController = segue.destinationViewController; 
    RecipeAddViewController *addController = (RecipeAddViewController *)navController.topViewController; 
    addController.delegate = self; // do didAddRecipe delegate method is called when cancel or save are tapped 
    addController.recipe = newRecipe; 
} 
+0

あなたの答えは、精度のためにAを取得します。トップコードスポッティング。ありがとうございました.... それは動作します。しかしそれはそうではありません。私はこれがあなたの正しい/そうでないためではないことを認めます。 – Chuck

+0

私はRecipeTypeを再設定しました。サブクラスを削除し、レシピクラスから既存のNSManagedObject *タイプを使用する。私はレシピタイプリストを取得し、スナックを選択すると2種類のスナックレシピが表示されます。驚くばかり。 – Chuck

+0

しかし、カテゴリリストに戻って別のタイプを選択するとクラッシュします。私は、アプリのシムを再起動し、別のタイプを選択し、正しいリストを渡します。しかし、レシピのないタイプを選択すると、空のテーブルが表示され、次に別のタイプを選択すると戻ってきても、空のテーブルを作成するレシピがいくつかあります。複数のコメントを申し訳ありません - 幸せを返す。 – Chuck

関連する問題