2

現在、対多関係でオブジェクトを削除する際に問題があります。

私のアプリには次の関係があります。

商品 <<- カート

ユーザーがビューコントローラーで「カートに追加」ボタンを押すと、次のコードは製品オブジェクトとカートの間の関係を設定しています

    + (Cart *)addProductToCartWithProduct:(Product *)product inManagedObjectContext:(NSManagedObjectContext *)context {

    Cart *cart = nil;

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Cart"];

    NSError *error = nil;
    NSArray *carts = [context executeFetchRequest:request error:&error];

    if (!carts || ([carts count] > 1)) {
        // handle error
    } else if (![carts count]) {
        cart = [NSEntityDescription insertNewObjectForEntityForName:@"Cart" inManagedObjectContext:context];


    } else { // they already have a cart started
        cart = [carts lastObject];
    }
    /*Get Object ID to safely pass NSMangedObject between threads (A background worker thread and the main thread). */
      NSManagedObjectID *retID = [product objectID];
    [cart addProductsObject:(Product *)[context objectWithID:retID]];

//Inverse relationship
    [(Product *) [context objectWithID:retID] setInCart:cart];


     return cart;
}

次に、これはカート オブジェクトを返します。これをカート ビュー コントローラーに渡し、次のようにその関係で製品をフェッチします。

             // Fetch request for "Product":
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Product"];

// Fetch only products for the cart:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"inCart = %@", self.cart];
[fetchRequest setPredicate:predicate]; 


NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"navn" ascending:YES];
[fetchRequest setSortDescriptors:@[sortDescriptor]];

self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_theManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;

次に、次のように関係からオブジェクトを削除しようとすると:

-(void)RemoveFromCart:(UIButton *)sender {

     NSIndexPath *ip = [NSIndexPath indexPathForRow:sender.tag inSection:0];

    Product *prod = (Product *)[self.fetchedResultsController objectAtIndexPath:ip];



       prod.inCart = nil;
       [_cart removeProductsObject:prod];


    NSLog(@"Cart %@ %@", _cart.products, prod);


    [self saveCurrentContext:_theManagedObjectContext];




    [self loadCart]; 
    [_orderTable reloadData];


}

inCartがnilに設定されているため、製品は視覚的に削除されます(テーブルビュー/画面から削除されます)が、技術的には削除されません...カートオブジェクトをログに記録すると、製品オブジェクトはまだ関係にあるため、機能し[_cart removeProductsObject:prod];ていないようです.

また、逆の場合も機能しません。同じ商品をカートに追加しようとすると、(カートから)削除しただけで、何らかの理由で逆の関係「inCart」が設定されていません。製品オブジェクトが削除された場合は、「nil」に設定します。

なぜこうなった?どうすれば修正できますか?:)。

編集:

コア データ モデル エディターで逆の関係を示す画像:

ここに画像の説明を入力

ここに画像の説明を入力

Cart を他のビューコントローラーに渡します。

[[[DataManager sharedInstance] backgroundManagedObjectContext] performBlock:^{


    UITabBarController *tabBarController = self.tabBarController; 

    for (UINavigationController *navController in  tabBarController.viewControllers) {


        for (UIViewController *vc in navController.viewControllers) {
            if ([vc isMemberOfClass:NSClassFromString(@"CartViewController")]){ 
               CartViewController *cartVC = (CartViewController *) vc;
                cartVC.cart = [Cart addProductToCartWithProduct:prod inManagedObjectContext:         [[DataManager sharedInstance] backgroundManagedObjectContext]];

                [[DataManager sharedInstance] saveBackgroundContext];
                [[DataManager sharedInstance] saveMasterContext];

                NSLog(@" %@", cartVC.cart); 
            }
        }

    }



}];

コンテキストを保存

-(void)saveCurrentContext:(NSManagedObjectContext *)context  {

    NSError *error = nil;
    if (![context save:&error]) {
        NSLog(@"NOT SAVED");
    }
    [[DataManager sharedInstance] saveBackgroundContext];
    [[DataManager sharedInstance] saveMasterContext];



}
4

1 に答える 1

4

さて、この非常に奇妙な問題の回避策を見つけました。自動生成されたアクセサー メソッドが何らかの理由で機能しなかったため、リレーションシップからオブジェクトを削除する別の方法を考える必要がありました。

          for (Product *prod in _cart.products) {

//To Very reliable to check for item by name attribute, but It works :) 
              if ([prod.name isEqualToString:product.name]) {

                        product = prod; 

       NSMutableSet *set = [NSMutableSet setWithSet:_cart.products];
       [set removeObject:prod];
       _cart.products = set;


              }


            }
于 2013-06-15T12:50:42.850 に答える