需求:
最近在项目中遇到一个需求:自动读取数据库中的纪录,并根据type字段分层,构建目录树。要求能够在点击父节点的时候动态刷新子节点,并完成相关操作。
在windows 环境中,自己也做过或者用过不少目录树的控件,但是ios平台没有自带的tree目录控件,ok,自己动手写一个。
思路:
开始自己想到过简单的用几个array来动态保存每个层级的元素,例如根结点为array1,一级节点就存在array2,三级节点放在array3 ......由此类推,n级节点就放在 arrayn+1中,这样做比较简单,实现起来不复杂,但是有几个致命的缺陷:
1、在层级不能确定的前提下,需要用一个动态数组保存每一级的元素集合,也就是需要二维数组,在每一次点击节点的时候,需要至少做一次查询,并对该二维数组进行修改。实现效率较低。
2、在层级确定的前提下,可以将数组个素确定,但是如果层级发生变化,需要修改,比较麻烦。
最后,自己考虑用树来保存目录结构,并根据点击要素所在的层级,动态更新显示子节点,该方法只需要在程序加载的时候查询一次数据库,大大提高以后的点击操作效率。下图是自己简单思考后画的草图。
实现:
1、定义树形结构,作为数据目录,并将它作为界面操作的数据源
2、定义数据结构,包括节点的子节点,节点名称,以及节点度
3、定义目录在界面上的展现形式,自定义控件。
4、数据库查询操作代码。
核心代码说明:
eTreeMenu.h
@protocol eTreeMenuDelegate<NSObject>
//多选情况,title : 选择名称 sel : 是否选择
-(void)ChooseItemClick:(NSString *)title andSel:(BOOL)sel;
//清除已经选择的叶子节点
-(void)clearChoosedLeaves;
@end
@interface eTreeNode : NSObject
{
eTreeNode *parentNode;
NSArray *childrenNode;
NSString *displayName;
NSInteger nodeDepth;
}
@property(nonatomic,assign) NSInteger nodeDepth;
@property(nonatomic,retain)NSString *displayName;
@property(nonatomic,retain)NSArray *childrenNode;
@property(nonatomic,retain)eTreeNode *parentNode;
@end
@interface eTreeMenu : UIScrollView<eChooseItemViewDelegate>
{
id<eTreeMenuDelegate> sdelegate;
NSMutableDictionary *dataSource;
eTreeNode *rootNode;
NSInteger depth;
float maxWidth;
float maxHeight;
sqliteCommand *sqlComd;
NSMutableArray *showNodes;
eTreeNode *Root;
//选中的node深度
NSInteger selectedNodeDepth;
}
@property(nonatomic,retain)id<eTreeMenuDelegate> sdelegate;
@property(nonatomic,retain)eTreeNode *Root;
@property(nonatomic,r