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

Core data 核心数据插入行和保存问题,core-data,uitableview,nsfetchedresultscontroller,nsmanagedobject,Core Data,Uitableview,Nsfetchedresultscontroller,Nsmanagedobject,我在将数据保存到核心数据和行组织中时遇到了一些问题,为了更好地理解我的问题所在,我将解释我的问题: 我有一个处理动态行的主表视图,在这个表视图中我有一个+按钮,每当按下+按钮时,一个表视图就会出现在弹出框中,用户可以选择要插入主表视图的“单元格类型”。“单元格类型”是自定义单元格,它们有一个类和xib文件。每个自定义单元格都有不同的文本字段…因此其想法是: 选择单元格类型并插入主表视图 用数据填充文本字段 保存的数据对应于插入的行数和文本字段中的数据 调用popover tableview时,我

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

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

  • 选择单元格类型并插入主表视图
  • 用数据填充文本字段
  • 保存的数据对应于插入的行数和文本字段中的数据
  • 调用popover tableview时,我的主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;
    }
    
    - (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..
       }
    }
    
    然后在我的popover tableview的didSelectRow中,我有:

    - (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;
    }
    
    - (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..
       }
    }
    
    从这里,一个单元格被插入我的主表视图,这里是我的主表视图相关方法:

    - (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;
    }
    
    - (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方法:(也有其他方法,但它们是标准方法)

    现在,如果我想退出主表视图并转到另一个表视图,我知道我必须在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的顶部,而不是插入前一行之后

  • 当我填充插入的第二行的文本字段(数量)时…退出tableview并返回…文本字段没有显示为已填充…我做错了什么

  • 如果我一次插入两行,就会出现上一个问题,但是如果我插入一行…退出tableview,然后返回并插入另一行…textfield金额将被保存

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

    谢谢你的时间


    关于

    您需要在输入数据后立即保存数据,而不仅仅是在视图从显示中删除时。一旦一个单元格被滚动到屏幕外,它就会被重新使用或删除,所以你必须在这之前保存你的文本。更改文本时,最佳位置是文本字段委托回调

    如果在保存前添加了两行,则表明内部状态已损坏(添加了第二行,但尚未保存第一行中的数据)

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

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


    您还应该考虑本地变量和实例变量之间的差异,因为您的代码似乎混淆了它们…

    您需要在数据输入后立即保存数据,而不仅仅是在视图从显示中删除时。一旦一个单元格被滚动到屏幕外,它就会被重新使用或删除,所以你必须在这之前保存你的文本。更改文本时,最佳位置是文本字段委托回调

    如果在保存前添加了两行,则表明内部状态已损坏(添加了第二行,但尚未保存第一行中的数据)

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

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


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

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