Iphone NSManagedObject的发布

Iphone NSManagedObject的发布,iphone,ios,core-data,nsmanagedobject,nszombie,Iphone,Ios,Core Data,Nsmanagedobject,Nszombie,我已经基于苹果CoreDataRecipes示例代码的一部分应用程序,可在 经过一些修改后,我花了好几个小时追踪一个bug,这个bug一定是我引入的,但我通过删除苹果代码中的两行代码解决了它 我在NSManagedDataObject配方中添加了一个author属性,在实现上——据我所知——与配方中已有的其他字符串属性完全相同。我的新属性在进入和离开IngreditDetailViewController控制的模式视图后变成僵尸。IngredientDetailViewController的解

我已经基于苹果CoreDataRecipes示例代码的一部分应用程序,可在

经过一些修改后,我花了好几个小时追踪一个bug,这个bug一定是我引入的,但我通过删除苹果代码中的两行代码解决了它

我在NSManagedDataObject配方中添加了一个author属性,在实现上——据我所知——与配方中已有的其他字符串属性完全相同。我的新属性在进入和离开IngreditDetailViewController控制的模式视图后变成僵尸。IngredientDetailViewController的解除锁定方法无效

- (void)dealloc {
    [recipe release];
    [ingredient release];
    [super dealloc];
}
追踪到错误后,我对配方和配料(另一个NSManagedObject)的发布进行了注释,我的应用程序现在似乎正在运行。我现在发现我的代码在有或没有这些释放调用的情况下都可以工作;这个错误一定是被我做的另一个更改修复的。我现在想知道

  • 为什么苹果的示例代码最初是这样写的
  • NSManagedObject配方的原始属性是什么,这意味着它们不易受到dealloc调用的僵尸化的影响
  • 如果以上这些还没有显示出我的无知,我应该指出,我对Objective C和iPhone开发还不熟悉,但我真的很想了解这里发生了什么

    根据评论进行编辑并更新:

    我现在无法通过取消注释这些行来复制僵尸的创建,很明显,在bug拍摄期间的另一个更改起到了作用。我最初提出的一些问题现在是无效的,但这让我对NSManagedObjects的release的使用更加困惑,因为现在的功能似乎与这些调用相同或不相同。我现在的主要问题是他们是否应该在那里。在IngCreditDetailView中保存时发生崩溃。以下是标题:

    @class Recipe, Ingredient, EditingTableViewCell;
    
    @interface IngredientDetailViewController : UITableViewController {
    @private
        Recipe *recipe;
        Ingredient *ingredient;
    
        EditingTableViewCell *editingTableViewCell;
    }
    
    @property (nonatomic, retain) Recipe *recipe;
    @property (nonatomic, retain) Ingredient *ingredient;
    
    @property (nonatomic, assign) IBOutlet EditingTableViewCell *editingTableViewCell;
    
    @end
    
    以及保存方法:

    - (void)save:(id)sender {
    NSManagedObjectContext *context = [recipe managedObjectContext];
    /*
     If there isn't an ingredient object, create and configure one.
     */
    if (!ingredient) {
    
        self.ingredient = [NSEntityDescription insertNewObjectForEntityForName:@"Ingredient" 
                                                        inManagedObjectContext:context];
    
        [recipe addIngredientsObject:ingredient];
    
    
        ingredient.displayOrder = [NSNumber numberWithInteger:[recipe.ingredients count]];
    
    
    }
    /*
     Update the ingredient from the values in the text fields.
     */
    EditingTableViewCell *cell;
    
    cell = (EditingTableViewCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    ingredient.name = cell.textField.text;
    
    cell = (EditingTableViewCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];
    ingredient.amount = cell.textField.text;
    /*
     Save the managed object context.
     */
    NSError *error = nil;
    
    if (![context save:&error]) {
    
        /*
         Replace this implementation with code to handle the error appropriately.
    
         abort() causes the application to generate a crash log and terminate. 
         You should not use this function in a shipping application, although it may be useful during development. 
         If it is not possible to recover from the error, display an alert panel that instructs the user to quit the 
         application by pressing the Home button.
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    
    [self.navigationController popViewControllerAnimated:YES];
    NSLog(@"in ingredient detail save after ingredient pop; - recipe.author is %@", recipe.author);
    }
    
    因为我是一个新用户,所以我不能将数据模型的屏幕截图放在这里,所以这里有一个链接:

    最后是配方标题:

    @interface ImageToDataTransformer : NSValueTransformer {
    }
    @end
    
    
    @interface Recipe : NSManagedObject {
    }
    
    @property (nonatomic, retain) NSString *instructions;
    @property (nonatomic, retain) NSString *name;
    @property (nonatomic, retain) NSString *overview;
    @property (nonatomic, retain) NSString *prepTime;
    @property (nonatomic, retain) NSSet *ingredients;
    @property (nonatomic, retain) UIImage *thumbnailImage;
    @property (nonatomic, retain) NSString *author;
    @property (nonatomic) BOOL *isDownloaded;
    @property (nonatomic) BOOL *isSubmitted;
    @property (nonatomic, retain) NSString *uniqueID;
    @property (nonatomic) float averageRating; 
    @property (nonatomic) float numberOfRatings;
    
    
    @property (nonatomic, retain) NSManagedObject *image;
    @property (nonatomic, retain) NSManagedObject *type;
    
    @end
    
    
    @interface Recipe (CoreDataGeneratedAccessors)
    - (void)addIngredientsObject:(NSManagedObject *)value;
    - (void)removeIngredientsObject:(NSManagedObject *)value;
    - (void)addIngredients:(NSSet *)value;
    - (void)removeIngredients:(NSSet *)value;
    @end
    

    再次感谢。

    请查看核心数据文档,因为核心数据“拥有”受管对象的生命周期,您根本不应该发布它们。

    请查看核心数据文档,因为核心数据“拥有”托管对象的生命周期您根本不应该释放它们。

    释放托管对象的唯一时间是您自己保留它的情况。鉴于您的属性定义表示它保留配方和配料对象,当解除分配IngReditionViewController时,它需要释放配方和配料对象

    当您执行类似myIngredientViewController.Component=Angredient的操作时,就像调用一个类似以下内容的方法:

    - (void)setIngredient:(Ingredient *)ing {
      [self willChangeValueForKey:@"ingredient"];
      Ingredient *oldIngredient = ingredient;
      ingredient = [ing retain];
      [oldIngredient release];
      [self didChangeValueForKey:@"ingredient"];
    }
    
    因此,在save方法中,当它指定self.component=…,这将保留您自己的对象-您现在拥有该对象的所有权权益,因此您需要在dealloc中释放它

    如果从另一个角度考虑,托管对象上下文将1添加到保留计数中,因为它在其中拥有所有权权益,而您将1添加到保留计数中,因为您希望在其中保留所有权权益。当您放弃所有权权益时,通过在dealloc期间释放所有权权益,保留计数将下降1,当托管对象上下文释放所有权权益时,保留计数将变为零,并且将被释放

    这就是普通对象的操作方式,以及在大多数情况下您将如何处理托管对象,但托管对象有几个注意事项-如前一张海报所示,托管对象的生命周期由托管对象上下文控制,托管对象可能会发生各种情况,这可能意味着,尽管该对象仍然存在,但它可能会在上下文中被删除,或在上下文中出现错误,甚至可能与不同的数据一起重用

    您通常不必担心这一点,但如果您使用自定义托管对象,这些对象有自己的实例变量,您需要为其管理内存,或者在创建、获取、转化为故障等时要执行的其他操作,那么您需要查看awakeFromInsert、awakeFromFetch、willturnintofult、,他犯了错误等

    但所有这些都是高级的东西,在你进入更复杂的场景之前,你不需要这些东西


    HTH

    只有在您自己保留托管对象的情况下,才会释放该对象。鉴于您的属性定义表示它保留配方和配料对象,当解除分配IngReditionViewController时,它需要释放配方和配料对象

    当您执行类似myIngredientViewController.Component=Angredient的操作时,就像调用一个类似以下内容的方法:

    - (void)setIngredient:(Ingredient *)ing {
      [self willChangeValueForKey:@"ingredient"];
      Ingredient *oldIngredient = ingredient;
      ingredient = [ing retain];
      [oldIngredient release];
      [self didChangeValueForKey:@"ingredient"];
    }
    
    因此,在save方法中,当它指定self.component=…,这将保留您自己的对象-您现在拥有该对象的所有权权益,因此您需要在dealloc中释放它

    如果从另一个角度考虑,托管对象上下文将1添加到保留计数中,因为它在其中拥有所有权权益,而您将1添加到保留计数中,因为您希望在其中保留所有权权益。当您放弃所有权权益时,通过在dealloc期间释放所有权权益,保留计数将下降1,当托管对象上下文释放所有权权益时,保留计数将变为零,并且将被释放

    这就是普通对象的操作方式,以及在大多数情况下您将如何处理托管对象,但对于托管对象有一些注意事项-如前一张海报所示,托管对象的生命周期由托管对象上下文控制,托管对象上可能发生的各种事情可能意味着