Iphone NSManagedObject的发布
我已经基于苹果CoreDataRecipes示例代码的一部分应用程序,可在 经过一些修改后,我花了好几个小时追踪一个bug,这个bug一定是我引入的,但我通过删除苹果代码中的两行代码解决了它 我在NSManagedDataObject配方中添加了一个author属性,在实现上——据我所知——与配方中已有的其他字符串属性完全相同。我的新属性在进入和离开IngreditDetailViewController控制的模式视图后变成僵尸。IngredientDetailViewController的解除锁定方法无效Iphone NSManagedObject的发布,iphone,ios,core-data,nsmanagedobject,nszombie,Iphone,Ios,Core Data,Nsmanagedobject,Nszombie,我已经基于苹果CoreDataRecipes示例代码的一部分应用程序,可在 经过一些修改后,我花了好几个小时追踪一个bug,这个bug一定是我引入的,但我通过删除苹果代码中的两行代码解决了它 我在NSManagedDataObject配方中添加了一个author属性,在实现上——据我所知——与配方中已有的其他字符串属性完全相同。我的新属性在进入和离开IngreditDetailViewController控制的模式视图后变成僵尸。IngredientDetailViewController的解
- (void)dealloc {
[recipe release];
[ingredient release];
[super dealloc];
}
追踪到错误后,我对配方和配料(另一个NSManagedObject)的发布进行了注释,我的应用程序现在似乎正在运行。我现在发现我的代码在有或没有这些释放调用的情况下都可以工作;这个错误一定是被我做的另一个更改修复的。我现在想知道
@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,当托管对象上下文释放所有权权益时,保留计数将变为零,并且将被释放
这就是普通对象的操作方式,以及在大多数情况下您将如何处理托管对象,但对于托管对象有一些注意事项-如前一张海报所示,托管对象的生命周期由托管对象上下文控制,托管对象上可能发生的各种事情可能意味着