1つのテーブルビューから別のテーブルにアイテムを移動する連結があるビュー

私は2つのUITableViewを景観モードのipadでお互いに隣に置いているとしましょう。 今私は1つのテーブルビューから複数のアイテムを移動したい。それらは他のtableViewの底に挿入することができます。どちらもmultiSelectionを有効にしています。

現在、動き自体は正常な細胞には問題ありません。しかし、私のプログラムでは、各セルには、セルのconsolidationStateを含むオブジェクトがあります。セルには、基本、保持、親、子の4つの状態があります。 基本=普通のセル。 保持=複数の子を含むが、この状態では表示されないセル。 Parent =複数の子を含み、このセルのすぐ下に表示されるセル。 子=親セルによって作成されたセル。

各セルのオブジェクトには、その子を含む配列もあります。オブジェクトには、セル自体に表示されるquantityValueも保持されます。

今や動きは厄介です。ホールディングと親セルはまったく動かない。基本細胞は自由に動くことができます。子セルは自由に移動できますが、親に残っている子セルの数に基づいています。親は変更されるか一緒に削除されます。 親セルに1つ以上の子セルが残っている場合、親セルに残ります。 そうでなければ、親には1つまたは2つの子セルが残っており、役に立たない。削除されます。

移動されるアイテムは常に同じ状態になります。それらはすべてBasicセルになります。

これが私の動きをプログラムした方法です:

*最初に、どのtableViewsが送信者であり、どの受信者が受信者であるかを判断します。

* 2番目は、すべてのindexPathsForSelectedRowsに問い合わせて、最上位から最下位に並べ替えます。

*次に、転送するデータを作成します。これは、selectedRowsをループし、送信者のlistOfItemsからオブジェクトを尋ねることで行います。

*必要なすべてのデータを保存すると、送信者のTableViewからすべてのアイテムが削除されます。これは、私がselectedRowをソートして、最高のindexPath.rowから開始し、他のindexPathsを壊すことなく削除できるようにする理由です。

  • * selectedRowsをループすると、状態がBasicまたはChildのセルが見つかったかどうかを確認します。

  • *基本セルの場合は何もせず、セルを削除するだけです。 (これはすべての基本セルでうまく動作します)

  • *子セルの場合は、すぐに親セルをチェックします。すべての子セルは親セルのすぐ下にあり、親の子がその親の下にないので、選択したChildcellのパスを安全に取得し、上方向に移動して親セルを見つけることができます。この親セルが見つかると(これはいつも起こりますが、例外はありません)、それに応じて変更する必要があります。

    • *親セルは削除されるか、内部のオブジェクトはその量と子が縮小されます。
  • *親セルがそれに応じて変更された後、基本セルと同様に子セルが削除されます。

*セルを削除した後、receiverViewViewは新しいindexPathsを作成しますので、movedObjectsに移動する場所があります。

*次に、レシーバTableViewのlistOfItemsにオブジェクトを挿入します。

コードは次のように動作します。 基本セルだけが移動されます。 基本セルと各親に対して1つの子が移動されます。 単一のBasic/Childセルが移動されます。

次の場合にコードは機能しません。 私はいくつかの親細胞の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= 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:Parent-Child-Childがリストの最後の3つの項目であり、それらをすべて選択して移動しようとするとクラッシュします。

この時点でも、単一のアイテムの動きが完璧に機能しました。


ただ1つのバグが終わったと思ったときには、 1つのChildCellをParentCellからすべて移動すると、ChildCellはBasicCellに戻りません。これは、テーブルからの2番目の動きを壊す可能性があるため、追加する必要がある重要な側面です。

次のような状況が発生した場合:

P-C-C-C-C-P-C-C

そして、次のように(xでマークして)選択します:

P-C-C-C-C-P-C-Cx

それは動きの後で次のように動作します:

P-C-C-C-C-C

期待している間: P-C-C-C-C-B

あなたが次回にそれを作ったときに、それは動きを台無しにするでしょう。 親の数は4ですが、その背後に5つの子セルがあります。 今のような細胞を選択するときは:

P-Cx-C-Cx-C-Cx

期待通り: P-Cx-C-Cx-C-Bx

4人の子供のうち2人しか選択されていないので、親を削除しないでください。しかし、これまでの動きとコードのおかげで、今では3人の子供が削除され、これを返すと考えられます。

C-C

期待されている: P-C-C

データソース内のアイテムを置き換えることは、恐ろしい仕事であることが判明しました。それは固執していないようです。


この最後のバグは今でも解決されました。

この不具合は、子供のインデックスを誤算することによって引き起こされました。データソースはまだ更新されていないので、Parent-Child構造の子のインデックスが残っているかどうかを確認して、+1の代わりにjに追加する必要がありました

このコードを newItem.quantity == 1 のチェックの後に追加しました

     //replace the one child that is left and make it basic
                int x;
                for (x = 1; x
2

1 答え

アップデート:実際にこのコードには多くの問題がありました。基本的に、selectedRows配列のNSIndexPathsに格納されている値は、親行がメイン配列から削除されると、期限切れになっていました。

ここでは、テストされたコードと作業コードがあります(OPの作業後)

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];
1
追加された
@tarmes:selectedRowsの代わりにtargetRowsを使って、 "path.rowを使用して配列のインデックスを作成すると停止します。これは適切に起こります。とにかく選択されている送信者のlistOfItemsのリストはtargetRowsであるためです。その項目の最新のものから始めて、selectedRowsの場合と同じように、indexPathsを壊すことなくほぼ同じことをすることができます。
追加された 著者 Totumus Maximus,
私のコードを変更して15分にする
追加された 著者 Totumus Maximus,
@tarmes:まだ動作していませんが、あなたのコードは意味があります。チャットで少し話してもらえますか?部屋を探す:「テーブルを使った統合された動き」
追加された 著者 Totumus Maximus,
あなたは今日の私のヒーローです:Dありがとう
追加された 著者 Totumus Maximus,
いくつかの大規模なテストの後に1つのバグが現れた。 1つの親セルから1つの子セル以外のすべてを移動すると、ChildCellは基本的なものに変更されず、上の可能な統合親をかなりねじ込みます。
追加された 著者 Totumus Maximus,
ObjectAtIndex:path.rowを削除するのではなく、removeObjectAtIndex:iを実行します。ここで、iは親の削除中にすでに減少しています。
追加された 著者 tarmes,
私もあなたのコードを更新しました - 私の更新答えを見てください:)
追加された 著者 tarmes,