核心数据插入行和保存问题

Posted

技术标签:

【中文标题】核心数据插入行和保存问题【英文标题】:Core data inserting rows and saving issue 【发布时间】:2013-04-22 21:38:47 【问题描述】:

我在将数据保存在核心数据以及行组织时遇到了一些问题,为了更好地了解我的问题,我将解释我的问题:

我有一个使用动态行的主表视图,在这个表视图中我有一个 + 按钮,每当按下 + 按钮时,如果用户可以选择要插入的“单元格类型”,则会在弹出框内出现一个表视图主表视图。 “单元格类型”是自定义单元格,它们是一类和 xib 文件。每个自定义单元格都有不同的文本字段......所以想法是:

    选择一种单元格类型并插入到主表格视图中。 用数据填充文本字段。 保存的数据与插入的行数和文本字段中的数据相对应。

当调用弹出表视图时,我的主表视图中有这个方法:

- (IBAction)Add:(id)sender


SelectProduct *typeProduct=[[self.storyboard instantiateViewControllerWithIdentifier:@"selectTable"]initWithTableViewTag:self.tableView.tag];
self.popover=[[UIPopoverController alloc]initWithContentViewController:typeProduct];
[popover presentPopoverFromBarButtonItem:buttonAdd permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
typeProduct.popView = self.popover;
typeProduct.cellSelected = self.cellSelected; //cellSelected is core data subclass.
typeProduct.delegate = self;
typeProduct.managedObjectContext = self.managedObjectContext;

然后在我的 popover tableview 的 didSelectRow 中,我有:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

row = indexPath.row;

if (row == 0)

    cellSelected=[NSEntityDescription insertNewObjectForEntityForName:@"CellSave" inManagedObjectContext:self.managedObjectContext];
    cellSelected.nameCellData = @"Olive";
    cellSelected.amountData = myCostumCell.amount.text;   

从这里,一个单元格被插入到我的主表视图中,这是我的主表视图相关方法:

- (void)viewDidLoad

[self.tableView registerNib:[UINib nibWithNibName:@"myCostumCellXib" bundle:nil] forCellReuseIdentifier:@"myCostumCell"];

AppDelegate *appDelegate =[[UIApplication sharedApplication] delegate];
self.managedObjectContext=[appDelegate managedObjectContext];

NSError *error = nil;
if (![self.fetchedResultsController performFetch:&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.
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();


[self fetchedResultsController];


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


static NSString *CellIdentifier = @"myCostumCell";

cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.cellSelected = self.cellSelected;
cell.managedObjectContext = self.managedObjectContext;

if (cell == nil)

    cell = [[MyCostumCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

cellSelected = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.nameCell.text = cellSelected.nameCellData;

if ([cellSelected.nameCellData isEqualToString:@"Olive"])
   
    cell.amount.text = cellSelected.amountData;
    // i have more textfields to assign but i think you understand the rest..
   

我的 fetchedResultsController 方法:(也有其他的,但它们是标准的东西)

- (NSFetchedResultsController *)fetchedResultsController


if (_fetchedResultsController != nil)

    return _fetchedResultsController;


// Create and configure a fetch request.
NSFetchRequest *fetchRequestCellSave = [[NSFetchRequest alloc] init];
NSEntityDescription *entityCellSave=
[NSEntityDescription entityForName:@"CellSave" inManagedObjectContext:self.managedObjectContext];
[fetchRequestCellSave setEntity:entityCellSave];

// Create the sort descriptors array.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"nameCellData" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequestCellSave setSortDescriptors:sortDescriptors];

_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequestCellSave managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"nameCellData" cacheName:nil];
_fetchedResultsController.delegate = self;
self.fetchedResultsController = _fetchedResultsController;

return _fetchedResultsController;



现在如果我想退出主表视图并转到另一个表视图,我知道我必须将文本字段的内容保存在我的 managedObject 中,所以:

- (void)viewWillDisappear:(BOOL)animated

[super viewWillDisappear:animated];

    cellSelected.amountData = cell.amount.text;

    //i have more textfields to assign but for the example i think you understand
      what i want.

    [self.managedObjectContext save:nil];


从这里开始,一行被“保存”并且数量中的文本也......但是当我再添加一行时问题就开始了:

    为什么新行出现在 tableview 的顶部,而不是在插入的前一行之后?

    当我填充插入的第二行的文本字段(数量)时...退出表格视图并返回...文本字段没有显示为填充...我做错了什么?

    如果我一次插入 2 行,则会发生上一个问题,但如果我插入一个...退出 tableview 然后返回并插入另一行...保存文本字段数量...

我的问题在哪里?它在我的自定义单元格中吗?在哪里?...我很抱歉发了这么长的帖子,但这让我发疯了...

感谢您的宝贵时间

问候

【问题讨论】:

【参考方案1】:

您需要在输入数据后立即保存数据,而不仅仅是在视图从显示中删除时。一旦单元格被滚动出屏幕,它将被重复使用或杀死,因此您必须在此之前保存您的文本。最好的地方是文本更改时的文本字段委托回调。

当您在保存之前添加 2 行时,您的内部状态已损坏(当添加了第二行但您尚未保存第一行的数据时)。

您的行按输入的文本排序,因此取决于文本(或缺少)来确定它在屏幕上的显示位置。

您可能不应该为单元格提供对托管对象上下文(不是 MVC)的引用。

您还应该考虑局部变量和实例变量之间的区别,因为您的代码似乎混淆了它们...

【讨论】:

您好 Wain,首先让我感谢您回复我的帖子,我真的迷路了。所以当您说:“您需要在输入数据后立即保存”您的意思是文本?所以我应该去我的服装单元类的 textfieldDidEndEditing 方法?我也应该在插入行时保存?另外我还有另一个正在处理核心数据的表格视图,当我想插入数据时,我按下 + 按钮,出现一个模态表格视图(静态单元格),然后我插入文本并正确保存但我使用的是动态标准行和所有行总是在彼此下方。 嗨。是的,-textFieldDidEndEditing 或 -shouldChangeCharactersInRange 委托方法可以工作。插入行时是否保存取决于您,您插入新实体但您是否将其归类为有效?如果你这样做,保存它。如果在它有一些文本之前它是无效的,那么在此之前不要保存它。 表中行的顺序由提供给获取结果控制器的排序描述符决定。 嗨 Wain,再次感谢。你是说我的问题可能是我首先在弹出表视图中执行此操作(文本字段中没有任何内容):cellSelected=[NSEntityDescription insertNewObjectForEntityForName:@"CellSave " inManagedObjectContext:self.managedObjectContext];然后我在文本字段中插入文本,这会让核心数据感到困惑吗? 如果有两行同名,则顺序不确定。如果您想更详细地指定顺序,请添加第二个排序描述符。

以上是关于核心数据插入行和保存问题的主要内容,如果未能解决你的问题,请参考以下文章

更改未保存在核心数据模型中(例如删除对象)

将多个复选框插入数据库 Html Php

核心数据获取...为啥在将托管对象插入上下文 A 并保存上下文 A 后,不使用上下文 B 获取托管对象?

核心数据需要时间来插入具有获取实体的记录并设置为关系

向tableview添加行以添加行和核心数据

将 JSON 保存到核心数据