Ios 核心数据,递归结构。。。我想
谢谢你的关注 我甚至不知道如何表达这个问题,更不用说寻找答案了。。。老实说,我已经试过了,所以需要所有的帮助 这可能很简单,因为我确信这是一种经常发生的模式: 我的模型(MainLevel*)中有一个与自身有关系的实体 实体用于法律的级别,唯一的要求是每个法律至少有一个(最高)级别。除此之外,从技术上讲,子级别的数量是无限的(但实际上通常约为5个,最多可能不超过8-10个)。正如所料,每个子级只有一个父级(MainLevel.parentLevel),任何父级都可以有多个(或零个)子级(NSSet*childLevels) 我想做的是将此关系的所有结构放在Ios 核心数据,递归结构。。。我想,ios,uitableview,core-data,Ios,Uitableview,Core Data,谢谢你的关注 我甚至不知道如何表达这个问题,更不用说寻找答案了。。。老实说,我已经试过了,所以需要所有的帮助 这可能很简单,因为我确信这是一种经常发生的模式: 我的模型(MainLevel*)中有一个与自身有关系的实体 实体用于法律的级别,唯一的要求是每个法律至少有一个(最高)级别。除此之外,从技术上讲,子级别的数量是无限的(但实际上通常约为5个,最多可能不超过8-10个)。正如所料,每个子级只有一个父级(MainLevel.parentLevel),任何父级都可以有多个(或零个)子级(NSSe
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];
}
然后在视图中将出现:
我有:
self.structure=[self-getStructureOfLawForLevel:self.selectedLevel]
有了这一点,我希望我的思路是正确的…(由于另一个问题,我现在正在整理,未经测试)
但是,我仍然不知道如何从此配置UITableView
或UICollectionView
。我的意思是,我确信我可以通过添加一两个计数器,这样得到行数和节数。这似乎太复杂了,我确信一定有一种更明显的方法,我只是没有看到
数据的唯一标准是必须按照实体实例的.order
属性对数据进行排序,而这不是唯一的。我的意思是,例如,每个childLevel可以有一个订单号为1的childLevel。它是该父级中的顺序
如果这个问题被问了一千次,我很抱歉。我试图寻找答案,但似乎没有找到我正在使用的搜索词
我没有做任何事情,除了把这些数据放在屏幕上,没有编辑,添加,删除。。。不确定这是否相关
为清晰起见进行编辑…
我不想做一个向下钻取类型的表视图。我希望在一个视图中获得整个结构的快照,然后可能需要从中向下钻取(使用与模型中其他实体的关系)
编辑我的解决方案
这就是我最后做的
- (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];
}
- (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中
我真的不喜欢递归。我不知道为什么,但我发现很难理解逻辑,当它完成时,它看起来很明显。。。算了吧
感谢大家的建议、帮助等。从TableView或CollectionView的ViewController开始,您应该先显示所有顶级对象(无父对象)。当用户从中选择一个对象时,父对象将成为当前级别,ViewController应刷新其数据源以显示该级别的所有子元素。然后,您可以通过“后退”按钮返回到父级
如果需要更多详细信息,请告诉我。从TableView或CollectionView的ViewController开始,您应该显示所有顶级对象(无父对象)。当用户从中选择一个对象时,父对象将成为当前级别,ViewController应刷新其数据源以显示该级别的所有子元素。然后,您可以通过“后退”按钮返回到父级
如果您需要更多详细信息,请告诉我。您的循环没有意义,因为您需要一个字典列表来描述子项的结构,但每次都要覆盖它。您可能需要以下内容:
NSMutableArray *subLevels = [NSMutableArray array];
for (MainLevel *childLevel in children)
{
[subLevels addObject:[self getStructureOfLawForLevel:childLevel]];
}
[mutableDict setObject:subLevels forKey:@"sublevels"];
我猜您希望在表视图中显示每个级别,并为每个后续级别钻取到另一个表视图。这应该很简单,因为字典为您提供了一个要显示的名称和一个可选的数组,该数组定义了是否可以进行钻孔以及要传递给下一个视图控制器的数据。您的循环没有意义,因为您需要一个字典列表来显示子对象的结构,但实际上你每次都会覆盖它。您可能需要以下内容:
NSMutableArray *subLevels = [NSMutableArray array];
for (MainLevel *childLevel in children)
{
[subLevels addObject:[self getStructureOfLawForLevel:childLevel]];
}
[mutableDict setObject:subLevels forKey:@"sublevels"];
我猜您希望在表视图中显示每个级别,并为每个后续级别钻取到另一个表视图。这应该很简单,因为字典为您提供了一个要显示的名称和一个可选的数组,该数组定义了是否可以进行钻孔以及要传递给下一个视图控制器的数据。编辑
对不起,我错过了说您想一次全部显示的部分。基本上,我认为最简单的方法是基本上有一个递归结构来获取每个对象的描述。这可以是一个字符串,甚至是一个UIView,然后可以将其放在tableviewcell中
现在我们还是用字典吧。每个字典表示都可以有关于其自身及其子项的信息。模板可以是:
<LevelInfoDictionary>
<NSObject>someObjectThatRepresentsInfoAboutThisLevel
<NSArray>arrayOfInfoDictionariesThatRepresentChildren
</LevelInfoDictionary>
然后,您可以使用排序描述符对正在使用的NSFetchRequest进行排序
或者,您可以使用父对象上的属性获取子对象,并将其存储在按排序描述符排序的数组中
我应该提到的另一件事是,当前排序描述符没有完成任何任务。您可能没有注意到这一点,因为您应该更改设计的其他部分,但由于NSDictionary没有顺序(它是一个哈希表),因此在将对象放入字典之前对其进行排序没有任何作用。EDIT
对不起,我错过了说您想一次全部显示的部分。基本上,我认为实现这一点最简单的方法是基本上有一个递归结构,该结构可以得到e的描述
#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
- (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];
}