iOS树形结构的通讯录实现
介绍
需求来自之前做过的一个项目,要求做一个多级部门的通讯录,每一级可能包含下级部门和员工;服务端返回部门和员工数组,以一个标志位做区分;要求按照拼音(即展示所有人员)和按照部门两种方式展示。
我的思路
我们的整个架构按照MVC模式,界面的实现比较简单,暂时跳过不谈,这里谈谈M的实现(其中涉及到了数据库操作,这里也略过不谈)。
1.我们把公司的整个架构看作一棵树,树的节点即某层次下的部门跟成员的合集。点击到任一部门,即得到该节点的成员。
2.由于有个计数的需求,也为了减少计算,对节点的数据做了一个扩充,增加了成员的数目这个字段,在构建树的时候即得到该节点下的成员数目。
具体实现
几个对象:EmployeeInfo
员工信息类
EmployeesList
员工列表(包含部门、员工)
ContactDBManager
数据库管理类(暂时不讲)
PinyinStructureNode
拼音树节点
PinyinStructure
拼音结构树
CompanyStructureNode
组织关系树节点
CompanyStructure
组织关系树
下面对每一个结构做介绍
EmployeeInfo
员工信息类
//员工信息
@interface EmployeeInfo : NSObject
@property (nonatomic, assign) NSInteger type;//0:员工;1:部门
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *ID;
@property(nonatomic,copy)NSString *parentName;//type=0员工所在部门名称 type=1上级部门名称
@property(nonatomic,copy)NSString *parentId;//type=0员工所在部门ID type=1上级部门ID
@property(nonatomic,copy)NSString *mobilePhone;//移动电话
//下面增加了字段,为了便于构造不同的树节点
@property(nonatomic,copy) NSString *namePinyin;//名字拼音
@property(nonatomic,copy) NSString *namePinyinPre;//名字拼音首字母(比方说:张三-》zs)
@property(nonatomic,copy) NSString *namePinyinFirstAlpha;//姓首字母(张三-》z)
@property(nonatomic,assign)NSInteger countOfPerson;//人员计数
- (instancetype)initWithInfo:(NSDictionary *)info;
+ (instancetype)employeeInfoWithWithDictionary:(NSDictionary *)dic;
@end
员工信息,这里我们把员工跟部门都当做员工信息,无非是类型不一样,服务端返回员工信息(type:0 员工 1 部门)
增加几个字段,具体实现无非是解析,增加字段,根据type,countOfPerson初始值设为0(部门)或者1(员工)。
PinyinStructureNode
拼音节点类
//拼音节点
@interface PinyinStructureNode : NSObject
@property(nonatomic,strong) NSString *alphaKey;//字母
@property(nonatomic,strong)NSMutableArray *persons;//成员数组
-(instancetype)initNodeWithPerson:(EmployeeInfo*)info;
-(void)addPerson:(EmployeeInfo*)info;
@end
这个实现比较简单,alphaKey代表成员姓的拼音首字母。
只有两个接口:构造,往节点增加成员。
PinyinStructure
拼音结构树
@interface PinyinStructure : NSObject
@property(nonatomic,strong) NSMutableDictionary *alphaIndexDic;
//所有分组
@property(nonatomic,strong)NSMutableArray *groups;
-(instancetype)initPinyinStructureWithPersonList:(NSMutableArray*)personList;
@end
这个实现比较简单,对通讯录做一个遍历,获得成员的拼音首字母,判断是否在分组字典alphaIndexDic
里面。在,则找到对应节点,往节点增加成员;不在,则构建对应的拼音节点PinyinStructureNode
,在alphaIndexDic
、groups
增加成员。
CompanyStructureNode
组织关系树节点
@interface CompanyStructureNode : NSObject
@property(nonatomic,strong) NSString *ID;
//两个数组:一个数组记录所有的子部门,一个数组记录下级所有的人
@property(nonatomic,strong)NSMutableArray *departmens;
@property(nonatomic,strong)NSMutableArray *persons;
-(instancetype)initNodeWithEmployeeInfo:(EmployeeInfo*)info fromDepList:(NSMutableArray*)depList andPersonList:(NSMutableArray*)personList;
-(instancetype)initNodeWithId:(NSString*)Id fromDepList:(NSMutableArray*)depList andPersonList:(NSMutableArray*)personList;
//某节点人员个数
-(NSInteger)personNumberOfNode;
@end
为了避免反复去算人数,这直接在存数据库到时候计算了某节点下的人数,而不是反复递归。
提供了三个接口:通过员工信息构造节点、通过ID构造节点、获得节点下所有员工数量。具体实现,无非就是遍历,遍历部门数组跟员工数组即可获得该级别下的所有部门和成员。
CompanyStructure
组织关系树
@interface CompanyStructure : NSObject
@property(nonatomic,strong)NSMutableArray *allDepartments;
@property(nonatomic,strong)NSMutableArray *allPersonInfo;
//辅助数组,用来计算某ID下面所有的人
@property(nonatomic,strong)NSMutableArray *subPersonsInfos;
-(instancetype)initStructureWithInfoList:(NSArray*)infoList;
//某节点下的人
-(NSArray*)personsUnderId:(NSString*)Id employeeType:(EmployeeType)type;
-(NSArray*)searchWithKeyword:(NSString*)keyword;
@end
这个结构相对会复杂一点,从解析到实现一步一步来讲可能会比较清楚。
-
服务端获得数据,解析生成
EmployeeInfo
员工信息,生成员工信息列表 -
遍历员工信息列表,往部门数组
allDepartments
和员工数组增加成员allPersonInfo
-
遍历员工数组,每获得一个员工,就更新其部门的人员计数,直到树的根节点。
这样,各部门的人员计数就获得了。
-
这样,要获得某层级的信息,无非调用
CompanyStructureNode
的构造方法。到此,整个树形结构的通讯录树就完成了。