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

时间:2013-04-22 21:38:48

标签: core-data uitableview nsfetchedresultscontroller nsmanagedobject

我在核心数据中保存数据时遇到了一些问题,并且还有行组织,为了更好地理解我的问题,我将解释我的内容:

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

  1. 选择一种单元格并插入主表视图。
  2. 用数据填充文本字段。
  3. 保存的数据对应于插入的行数和文本字段中的数据。
  4. 在调用popover tableview时,我在主表视图中有这个方法:

    - (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;
    }
    

    然后在我的popSetable 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;   
    }
    

    从这里开始,在我的主tableview中插入一个单元格,这是我的主要tableview相关方法:

    - (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;
    
    
    }
    

    现在,如果我想退出主tableview并转到另一个tableview,我明白我必须在我的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];
    
    }
    

    从这里开始,“保存”一行,金额中的文字也是......但是当我再添加一行时问题就开始了:

    1. 为什么新行显示在tableview的顶部,而不是在插入上一行之后?

    2. 当我填写插入的第二行的textField(金额)时...退出tableview并返回...文本字段不显示已填充..我做错了什么?

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

    4. 我的问题在哪里?它是我的自定义单元类吗?在哪里?...我很抱歉这篇长篇文章,但这让我发疯了......

      感谢您的时间

      此致

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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