2011-11-25 98 views
2

移动项目比方说,我有2个UITableViews旁边的海誓山盟在横向模式下的iPad上。 现在我想将多个项目从一个tableView移动到另一个。它们被允许插入到另一个tableView的底部。两者都激活了多选。从一个的tableView到另一个的tableView与整合

现在运动本身对正常细胞没有问题。但在我的程序中,每个单元格都有一个包含单元格的合并状态的对象。有一个单元格可以拥有4个状态:基本,控制,父,子。 Basic =普通单元格。 Holding =包含多个孩子但不会在此状态下显示的单元格。 Parent =包含多个子元素并直接显示在此单元格下方的单元格。 Child =由父单元格创建的单元格。

在每个单元中的对象也具有一定的数组,它包含其子。该对象还包含一个quantityValue,它显示在单元格本身上。

现在运动变得棘手。持有和父母细胞根本无法移动。基本细胞可以自由移动。子单元格可以自由移动,但基于父类中剩下多少个子单元格。父母将一起更改或删除。 如果父级单元有多于1个子单元,则它将保留父级单元。 否则,父没有或1个孩子单元格留下,是无用的。它将被删除。

移动的项目将始终处于相同的状态。他们都将是基本单元格。

这是我的编程的运动:

*首先,我确定哪个tableViews的是发送者,哪个是接收器。

*其次,我要求所有indexPathsForSelectedRows从最高排序排他们最低。

*然后我建立要传输的数据。这是通过遍历selectedRows并通过发送者的listOfItems询问它们的对象来完成的。

*当我保存所有的数据,我需要我删除发送TableView中的所有项目。这就是为什么我对selectedRows进行排序的原因,这样我就可以从最高的indexPath.row开始,并删除而不删除其他indexPath。

  • *当我遍历selectedRows时,检查是否找到一个状态为Basic或Child的单元格。

  • *如果它的一个基本的我什么也不做,只是删除单元格。 (这工作正常与所有基本单元)

  • *如果它的一个子细胞我去检查它的亲本细胞immidiately。由于所有子单元格都直接位于父单元格的下方,并且没有其他父类别的子单元低于该父单元格,所以我可以安全地获取所选的单元格的路径并向上移动并找到它的父单元格。当找到这个父级单元格时(这将始终发生,没有例外),它必须相应地改变。

    • *将删除父级单元格,或者内部的对象将减少其子数量和子级。母细胞作了相应的改变
  • *后的儿童的细胞也同样被删除,如基本单元

*后删除细胞接收器的tableView将建立新的indexPaths所以movedObjects会有一个地方要走。

*然后将对象插入到接收器TableView的listOfItems中。

该代码的工作原理如下: 只有基本单元格被移动。 基本单元和每个父母只是1名儿童被移动。 单个基本/子单元格被移动。

该代码在下列情况下不起作用: 我选择了多于一个或某些父级单元的所有子级。

问题发生的地方进入更新母细胞。我现在盲目地盯着代码,所以也许新的外观会帮助解决问题。任何帮助将不胜感激。

这是应该做的运动方法:

-(void)moveSelectedItems 
{ 
    UITableView *senderTableView = //retrieves the table with the data here. 
    UITableView *receiverTableView = //retrieves the table which gets the data here. 

    NSArray *selectedRows = senderTableView.indexPathsForSelectedRows; 

    //sort selected rows from lowest indexPath.row to highest 
    selectedRows = [selectedRows sortedArrayUsingSelector:@selector(compare:)]; 

    //build up target rows (all objects to be moved) 
    NSMutableArray *targetRows = [[NSMutableArray alloc] init]; 
    for (int i = 0; i<selectedRows.count; i++) 
    { 
     NSIndexPath *path = [selectedRows objectAtIndex:i]; 
     [targetRows addObject:[senderTableView.listOfItems objectAtIndex:path.row]]; 
    } 

    //delete rows at active 
    for (int i = selectedRows.count-1; i >= 0; i--) 
    { 
     NSIndexPath *path = [selectedRows objectAtIndex:i]; 

     //check what item you are deleting. act upon the status. Parent- and HoldingCells cant be selected so only check for basic and childs 
     MyCellObject *item = [senderTableView.listOfItems objectAtIndex:path.row]; 
     if (item.consolidatedState == ConsolidationTypeChild) 
     { 
      for (int j = path.row; j >= 0; j--) 
      { 
       MyCellObject *consolidatedItem = [senderTableView.listOfItems objectAtIndex:j]; 
       if (consolidatedItem.consolidatedState == ConsolidationTypeParent) 
       { 
        //copy the consolidated item but with 1 less quantity 
        MyCellObject *newItem = [consolidatedItem copyWithOneLessQuantity]; //creates a copy of the object with 1 less quantity. 

        if (newItem.quantity > 1) 
        { 
         newItem.consolidatedState = ConsolidationTypeParent; 
         [senderTableView.listOfItems replaceObjectAtIndex:j withObject:newItem]; 
        } 
        else if (newItem.quantity == 1) 
        { 
         newItem.consolidatedState = ConsolidationTypeBasic; 
         [senderTableView.listOfItems removeObjectAtIndex:j]; 

         MyCellObject *child = [senderTableView.listOfItems objectAtIndex:j+1]; 

         child.consolidatedState = ConsolidationTypeBasic; 

         [senderTableView.listOfItems replaceObjectAtIndex:j+1 withObject:child]; 
        } 
        else 
        { 
         [senderTableView.listOfItems removeObject:consolidatedItem]; 
        } 
        [senderTableView reloadData]; 
       } 
      } 
     } 
     [senderTableView.listOfItems removeObjectAtIndex:path.row]; 
    } 
    [senderTableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationTop]; 

    //make new indexpaths for row animation 
    NSMutableArray *newRows = [[NSMutableArray alloc] init]; 
    for (int i = 0; i < targetRows.count; i++) 
    { 
     NSIndexPath *newPath = [NSIndexPath indexPathForRow:i+receiverTableView.listOfItems.count inSection:0]; 
     [newRows addObject:newPath]; 
     DLog(@"%i", i); 

     //scroll to newest items 
     [receiverTableView setContentOffset:CGPointMake(0, fmaxf(receiverTableView.contentSize.height - recieverTableView.frame.size.height, 0.0)) animated:YES]; 
    } 

    //add rows at target 
    for (int i = 0; i < targetRows.count; i++) 
    { 
     MyCellObject *insertedItem = [targetRows objectAtIndex:i]; 

     //all moved items will be brought into the standard (basic) consolidationType 
     insertedItem.consolidatedState = ConsolidationTypeBasic; 

     [receiverTableView.ListOfItems insertObject:insertedItem atIndex:receiverTableView.ListOfItems.count]; 
    } 

    [receiverTableView insertRowsAtIndexPaths:newRows withRowAnimation:UITableViewRowAnimationNone]; 
} 

如果任何人有,为什么移动窃听出来让我知道了一些新鲜的想法。如果你觉得你需要一些额外的信息,我会很乐意添加它。 同样的问题在ChildCells的运动和适当的更新ParentCells。

我可以使用一些新鲜的外观和局外人的想法。

在此先感谢。


*更新基于意见

有了这个代码有2个错误得不到解决:

Bug1:选择所有这些,然后移动它们留下的子单元 BUG2:当父子-Child是列表中的最后3个项目,然后尝试将它们全部选中并将它们移至崩溃位置。

再次单项运动在这个时候工作完美。


正当你以为这是在一个单一的缺陷依然存在: 当您移动所有,但一个ChildCell从ParentCell的ChildCell不会得到改变回BasicCell。这是需要添加的一个重要方面,因为它可能会在桌子上产生第二次移动。

当你有一个情况如下:

PCCCCPCC

你选择(用x标记)是这样的:

PCCCCPC-CX

它就像这个运动之后:

PCCCCC

虽然期待: P-C-C-C-C-B

这将你把它下一次搞砸了的运动。 此处的父项数量为4,但其后有5个子单元格。 当你现在选择的细胞是这样的:

P-CX-C-CX-C-CX

同时预计: P-CX-C-CX-C-BX

父母不应被删除,因为其4个孩子中只有2个被选中。但由于之前的运动和代码,因为它现在是他会认为其子女3被删除,并且将返回此:

CC

虽然预期: PCC

更换项目在数据源中被证明是一项可怕的任务。它似乎并不坚持。


这最后一个bug现在也解决了。

该错误是由错误计算孩子的指数造成的。由于数据源尚未更新,我需要检查Parent-Child结构中的哪个子索引仍然存在,并将其添加到j,而不仅仅是+1。检查

 //replace the one child that is left and make it basic 
       int x; 
       for (x = 1; x<consolidatedItem.quantity; x++) 
       { 
        MyCell *cell = (MyCell *)[sender cellForRowAtIndexPath:[NSIndexPath indexPathForRow:x+j inSection:0]]; 
        if (![cell isSelected]) 
        { 
         break; 
        } 
       } 

       MyCellItem *lastChild = [sender objectAtIndex:j+x]; 
       MyCellItem *newChild = [lastChild copyToConsolidatedStateBasic]; 
       [sender.listOfItems replaceObjectAtIndex:j+x withObject:newChild]; 

回答

1

更新:实际上这个代码有很多问题。原则上,一旦从主数组中删除父行,存储在selectedRows数组的NSIndexPaths中的值将变得过时。

这里的测试,工作代码

for (int i = selectedRows.count-1; i >= 0; i--) 
{ 
    NSIndexPath *path = [selectedRows objectAtIndex:i]; 

    //check what item you are deleting. act upon the status. Parent- and HoldingCells cant be selected, so the only check that will be made are on child and basic cells 
    MyCellObject *item = [sender.listOfItems objectAtIndex:path.row]; 
    if (item.consolidatedState == ConsolidationTypeChild) 
    { 
     for (int j = path.row; j >= 0; j--) 
     { 
      MyCellObject *consolidatedItem = [sender.listOfItems objectAtIndex:j]; 
      if (consolidatedItem.consolidatedState == ConsolidationTypeParent) 
      { 
       //copy the consolidated item but with 1 less quantity 
       MyCellObject *newItem = [consolidatedItem copyWithOneLessQuantity]; 

       if (newItem.quantity > 1) 
       { 
        newItem.consolidatedState = ConsolidationTypeParent; 
        [sender.listOfItems replaceObjectAtIndex:j withObject:newItem]; 
       } 
       else if (newItem.quantity == 1) 
       { 
        MyCellObject *child = [sender.listOfItems objectAtIndex:j+1]; 
        child.consolidatedState = ConsolidationTypeBasic; 
        [sender.listOfItems replaceObjectAtIndex:j+1 withObject:child]; 
       } 

       if (newItem.quantity <= 1) { 

        [sender.listOfItems removeObjectAtIndex:j]; 

        // Update indexPath row values for selected items that are above the removed row 

        for (int k = i; k >= 0; k--) 
        { 
         NSIndexPath *aPath = [selectedRows objectAtIndex:k]; 
         if (aPath.row >= j) 
         { 
          [selectedRows replaceObjectAtIndex:k withObject:[NSIndexPath indexPathForRow:(aPath.row -1) inSection:0]]; 
         } 
         else 
         { 
          break; 
         } 
        } 

        path = [NSIndexPath indexPathForRow:(path.row -1) inSection:0] 
       } 
      } 
     } 
    } 

    [sender.listOfItems removeObjectAtIndex:path.row]; 
+0

@tarmes(与OP加工后):我想我应该用targetRows代替selectedRows工作,使“使用path.row索引数组,停止自认为”一旦你移除父母,你会过时。“这发生得很好。由于targetRows是无论如何都选择的发件人listOfItems的列表。我可以从最新的项目开始,并且与selectedRows几乎完全相同,但不会搞砸indexPath。 –

+0

而不是removeObjectAtIndex:path.row做removeObjectAtIndex:我,其中我已经减少父母的删除期间。 – tarmes

+0

给我15分钟,更新我的代码,只是这些变化;) –

相关问题