0

ご覧いただきありがとうございます...

答えを探すどころか、この質問をどのように表現すればよいかさえわかりません...正直に言って、すべての助けが必要だったので、すべての助けが必要です!

これは常に発生するパターンであると確信しているため、おそらく非常に単純です。

モデル (MainLevel*) にエンティティがあり、それ自体と関係があります。

エンティティは法律のレベルのためのものであり、唯一の要件は、各法律に少なくとも 1 つの (最上位の) レベルがあることです。それ以上のサブレベルの数は、技術的には無限です (ただし、実際には、通常は約 5 であり、多くても 8 ~ 10 を超えない可能性があります)。当然のことながら、各子レベルには 1 つの親 (MainLevel.parentLevel) しかなく、どの親にも複数 (またはゼロ) の子 (NSSet *childLevels) を持つことができます。

私がやりたいことは、この関係のすべての構造を取得して、UITableViewまたは collectionView に入れることです。

次のような再帰関数があります。

- (NSDictionary *)getStructureOfLawForLevel:(MainLevel *)level
{
    NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc]initWithCapacity:50];
    MainLevel *currentLevel = level;
    [mutableDict setObject:currentLevel.shortName forKey:@"name"];
    if (level.childLevels) {
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES];
        NSArray *sortdescriptors = @[sortDescriptor];
        NSArray *children = [currentLevel.childLevels sortedArrayUsingDescriptors:sortdescriptors];
        for (MainLevel *childLevel in children)
        {
            NSDictionary *dict = [self getStructureOfLawForLevel:childLevel];
            [mutableDict setObject:dict forKey:@"sublevels"];
        }
    }
    return [mutableDict copy];
}

それからviewWillAppear:私はこれを持っています:

self.structure = [self getStructureOfLawForLevel:self.selectedLevel]

これで、私が正しい方向に進んでいることを願っています...(現在ソート中の別の問題のためにテストされていません)。

UITableViewただし、これから aまたは aを構成する方法はまだわかりUICollectionViewません。つまり、カウンターを1つまたは2つ追加して、行数とセクション数を取得することで、それができると確信しています。それは非常に複雑に思えますが、私が見ていないより明白な方法があるに違いないと確信しています...

.orderデータの唯一の基準は、エンティティ インスタンスの属性によって順序付けする必要があり、それは一意ではないということです。たとえば、各 childLevel は順序番号 1 の childLevel を持つことができます。これは、その親レベルでの順序です。

これが何千回も尋ねられた場合は申し訳ありません。答えを検索しようとしましたが、使用している検索用語が見つからないようです。

画面に表示する、編集しない、追加する、削除する以外は、このデータで何もしていません...それが関連しているかどうかはわかりません。

わかりやすくするために編集...

ドリルダウン タイプのテーブル ビューを実行するつもりはありません。構造全体のスナップショットを 1 つのビューに表示したいのですが、そこから (モデル内の他のエンティティとの関係を使用して) ドリルダウンする必要がある場合があります。

私のソリューションの編集

これが私がやったことです...

- (NSArray *)getStructureAsArrayForLevel:(MainLevel *)child
{
    NSMutableArray *thisChildAndChildren = [[NSMutableArray alloc]initWithCapacity:2];
    [thisChildAndChildren addObject:child];
    if (child.childLevels)
    {
        // children exist
        // sort the children into order
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES];
        NSArray *sortdescriptors = @[sortDescriptor];
        NSArray *children = [child.childLevels sortedArrayUsingDescriptors:sortdescriptors];
        // get an array for each child via recursion
        for (MainLevel *child in children)
        {
            [thisChildAndChildren addObject:[self getStructureAsArrayForLevel:child]];
        }
    }
    return [thisChildAndChildren copy];
}

次に、同様の再帰関数を使用して配列を NSAttributedString に変換し、textView に表示します。

私は本当に再帰が好きではありません。理由はわかりませんが、ロジックを理解するのはとても難しいと思います。

提案、助けなどをくれたみんなに感謝します...

4

5 に答える 5

2

サードパーティのコントローラーを使用できる場合は、TLIndexPathToolsをご覧ください。ツリー構造を処理します。たとえば、Outlineサンプル プロジェクトを実行してみてください。

View Controller は次のようになります (大したことではありません)。

#import "TLTableViewController.h"
@interface TableViewController : TLTableViewController
@end

#import "TableViewController.h"
#import "TLIndexPathTreeItem.h"
@implementation TableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    MainLevel *topLevel = nil;//get the top level object here
    TLIndexPathTreeItem *topItem = [self treeItemForLevel:topLevel depth:0];
    self.indexPathController.dataModel = [[TLTreeDataModel alloc] initWithTreeItems:@[topItem] collapsedNodeIdentifiers:nil];
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    // customize cell configuration here
    TLIndexPathTreeItem *item = [self.dataModel itemAtIndexPath:indexPath];
    MainLevel *level = item.data;
    cell.textLabel.text = [level description];
}

- (TLIndexPathTreeItem *)treeItemForLevel:(MainLevel *)level depth:(NSInteger)depth
{
    NSMutableArray *childItems = [NSMutableArray arrayWithCapacity:50];    
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES];
    NSArray *sortdescriptors = @[sortDescriptor];
    NSArray *children = [level.childLevels sortedArrayUsingDescriptors:sortdescriptors];
    for (MainLevel *child in children) {
        TLIndexPathTreeItem *childItem = [self treeItemForLevel:child depth:depth + 1];
        [childItems addObject:childItem];
    }
    //set identifier to some unique identifier, if one exists. Otherwise, the item itself
    //will be used as the identifier
    id identifier = nil;
    //set cell identifier based on depth. This can be set to something unique for each
    //depth, or set to a constant value. If nil, the value "Cell" is assumed.
    NSString *cellIdentifier = [NSString stringWithFormat:@"Cell%d", depth];
    //pass "level" to the data argument. Or pass any other data, e.g. include the depth @[@(depth), level]
    TLIndexPathTreeItem *item = [[TLIndexPathTreeItem alloc] initWithIdentifier:identifier sectionName:nil cellIdentifier:cellIdentifier data:level andChildItems:children];
    return item;
}

@end

TLTreeTableViewController折りたたみ可能なレベルが必要な場合は、代わりにサブクラス化できTLTableViewControllerます。さらにサポートが必要な場合はお知らせください。

于 2013-06-20T19:08:13.247 に答える
1

編集 申し訳ありませんが、一度に表示したいという部分を見逃しました。基本的に、これを行う最も簡単な方法は、基本的に各オブジェクトの説明を取得する再帰構造を持つことだと思います。これは、tableviewcell 内に配置できる文字列または UIView である可能性があります。

今のところ辞書に固執しましょう。各ディクショナリ表現には、それ自体とその子に関する情報を含めることができます。テンプレートは次のいずれかです。

<LevelInfoDictionary>
    <NSObject>someObjectThatRepresentsInfoAboutThisLevel
    <NSArray>arrayOfInfoDictionariesThatRepresentChildren
</LevelInfoDictionary>

次に、再帰メソッドを実装します。

- (NSDictionary *)getLevelInfo
{
    NSMutableArray *childInfo = [NSMutableArray array];
    for(ClassName *child in self.children)
    {
         [childInfo addObject:[child getLevelInfo]];
    }
    return [NSDictionary dictionaryWithObjectsAndKeys:
                         <descriptionOfThisLevel>, @"CurrentLevel",
                         childInfo, @"children>, nil];

}

END EDIT 基本的に、これらの他の人の何人かが言ったように、トップレベルのオブジェクトをすべて表示するテーブルビューを作成する必要があります。そこから、オブジェクトを選択した後、次のような述語で別のフェッチ要求を使用する新しいテーブルビューにプッシュする必要があります。

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"parent = %@",
      selectedParentObject];

次に、ソート記述子を使用して、使用している NSFetchRequest をソートできます。

または、親オブジェクトのプロパティを使用して子を取得し、それを並べ替え記述子で並べ替えられた配列に格納することもできます。

もう 1 つ言及する必要があるのは、現在、並べ替え記述子は何も達成していないということです。変更する必要があるデザインの他の部分があるため、これに気付かない場合がありますが、NSDictionary には順序がないため (これはハッシュ テーブルです)、オブジェクトをディクショナリに配置する前に並べ替えても何も起こりません。

于 2013-06-20T18:42:46.570 に答える
0

TableView または CollectionView の ViewController から、すべての最上位オブジェクト (親なし) を表示することから始めます。そこからユーザーがオブジェクトを選択すると、その親が現在のレベルになり、ViewController はそのデータ ソースを更新して、そのレベルのすべての子要素を表示する必要があります。その後、戻るボタンを使用して親に戻ることができます。

詳細が必要な場合はお知らせください。

于 2013-06-20T18:23:35.607 に答える
0

それが他の誰かを助ける場合に備えて、これが私がやったことです...

- (NSArray *)getStructureAsArrayForLevel:(MainLevel *)child
{
    NSMutableArray *thisChildAndChildren = [[NSMutableArray alloc]initWithCapacity:2];
    [thisChildAndChildren addObject:child];
    if (child.childLevels)
    {
        // children exist
        // sort the children into order
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES];
        NSArray *sortdescriptors = @[sortDescriptor];
        NSArray *children = [child.childLevels sortedArrayUsingDescriptors:sortdescriptors];
        // get an array for each child via recursion
        for (MainLevel *child in children)
        {
            [thisChildAndChildren addObject:[self getStructureAsArrayForLevel:child]];
        }
    }
    return [thisChildAndChildren copy];
}

次に、同様の再帰関数を使用して配列を NSAttributedString に変換し、textView に表示します。

私は本当に再帰が好きではありません。理由はわかりませんが、ロジックを理解するのはとても難しいと思います。

提案、助けなどをくれたみんなに感謝します...

編集

最初のレイヤーは、それに続くレイヤーとは構造が少し異なるため、正確ではありません。ある時点で、これを変更して最上位レベルをディレクトリとして使用し、最初のレベルをディレクトリのキーとして使用してから、完全な配列をそのキーのオブジェクトとして追加する必要があります。しかし、それは機能します... 頭が痛いです...そして、それを変更するまで、私はそれと一緒に暮らすことができます.

于 2013-06-21T14:07:15.870 に答える
0

子の構造の辞書のリストが必要なため、ループは意味がありませんが、実際に毎回上書きするために何をしますか。おそらく次のようなものが必要です。

NSMutableArray *subLevels = [NSMutableArray array];

for (MainLevel *childLevel in children)
{
    [subLevels addObject:[self getStructureOfLawForLevel:childLevel]];
}

[mutableDict setObject:subLevels forKey:@"sublevels"];

テーブル ビューで各レベルを表示し、後続の各レベルの別のテーブル ビューにドリルダウンする必要があると思います。これは、表示する名前を与えるディクショナリと、ドリルが可能かどうかを定義するオプションの配列と、次のビュー コントローラに渡すデータに基づいて単純なはずです。

于 2013-06-20T18:24:54.687 に答える