我已经将一个应用程序的一部分建立在苹果的CoreDataRecipes示例代码之上
http://developer.apple.com/library/ios/#samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html
经过一些修改后,我花了几个小时来追踪一个我一定介绍过的bug,但我通过删除苹果代码中的两行代码来解决这个问题。
我在NSManagedDataObject菜谱中添加了一个author属性,在实现上(据我所知)与已经使用的其他字符串属性相同。在输入和离开由IngredientDetailViewController控制的模态视图后,我的新属性变成了僵尸。IngredientDetailViewController的脱钙方法是:
- (void)dealloc {
[recipe release];
[ingredient release];
[super dealloc];
}在追踪了bug之后,我评论了配方和配料(另一个NSManagedObject)上的版本,我的应用程序现在似乎正在运行。我现在发现,我的代码可以使用这些发布调用,也可以不使用;该bug肯定是通过我所做的另一项更改来修复的。我现在想知道
如果上面的内容没有充分显示出我的无知,我应该指出,我对目标C和iPhone开发是新手,但我真的很想了解这里发生了什么。
根据评论意见编辑并更新:
我现在无法复制僵尸创造通过取消评论这些行,很明显,另一个变化,在错误射击的诀窍。我最初询问的一些内容现在无效,但这使我对NSManagedObjects发布的使用更加困惑,因为现在的功能似乎与这些调用相同或不相同。我现在的主要问题是他们是否应该在场。坠机是在保存在IngredientDetailView中时发生的。以下是标题:
@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再次感谢。
发布于 2011-05-27 14:43:03
请看一下Core数据文档,因为Core数据“拥有”托管对象的生命周期,因此根本不应该发布它们。
发布于 2011-07-29 04:39:05
唯一释放托管对象的时间是您自己保留它的时候。鉴于您的属性定义表明它保留了配方和配料对象,当您的ingredientviewcontroller被解除分配时,它需要释放配方和配料对象。
当您执行类似于myIngredientViewController.ingredient = anIngredient的操作时,它就像调用一个类似于以下内容的方法:
- (void)setIngredient:(Ingredient *)ing {
[self willChangeValueForKey:@"ingredient"];
Ingredient *oldIngredient = ingredient;
ingredient = [ing retain];
[oldIngredient release];
[self didChangeValueForKey:@"ingredient"];
}因此,在您的保存方法中,当它指定self.ingredient =.时,即自己保留对象--您现在对该对象有了所有权,所以您需要在dealloc中释放它。
如果您以另一种方式考虑它,托管对象上下文已经将1添加到保留计数中,因为它对其有所有权兴趣,而您已经将1添加到保留计数中,因为您希望保持它的所有权兴趣。当您放弃所有权兴趣时,通过在dealloc期间释放它,保留计数将下降1,当托管对象上下文释放它时,保留计数将变为零,并且将被解除分配。
这就是普通对象的操作方式,以及在大多数情况下如何处理托管对象,但对于托管对象有一些警告--正如前面的海报所指出的,托管对象的生命周期由托管对象上下文控制,托管对象可能会发生各种事情,这可能意味着尽管对象仍然存在,但它可能在上下文中被删除,或者在上下文中出现错误,甚至可能与不同的数据重复使用。
您通常不必担心这一点,但是如果您使用自定义托管对象,这些对象有它们自己的实例变量,您需要为它们管理内存,或者在创建、获取、转换为错误等时您想要做的其他事情,那么您需要查看awakeFromInsert、awakeFromFetch、willTurnIntoFault、didTurnIntoFault等。
但所有这些都是高级的东西,除非你进入更复杂的场景,否则你不会需要这些东西。
HTH
https://stackoverflow.com/questions/6147363
复制相似问题