QQ好友列表很炫?其实很简单!

本文介绍了QQ好友列表的实现原理,通过分析plist文件揭示了其数据组织方式。每组好友信息存储为一个组模型,其中包含一个friends数组,用于保存该组内的所有好友。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信地球人都用QQ的,我们每天都会打开QQ,但是你去注意到他是怎么实现的吗?
话不多说先上图:
这里写图片描述

该数据都是用plist文件存储
接下来带你看下plist文件分析下数据结构

图一:
这里写图片描述
每一组都是一个组模型,一组相当于一个好友分组。

图二
这里写图片描述
每组里面都有一个friends数组存放该组的好友数

@interface JFFriend : NSObject
/**
 *  头像
 */
@property (nonatomic ,copy)NSString *icon;
/**
 *  个性签名
 */
@property (nonatomic ,copy)NSString *intro;
/**
 *  名字
 */
@property (nonatomic ,copy)NSString *name;
/**
 *  getter这样写的好处是控制get方法在需要的时候非常顺
 *  苹果官方建议这样写:规范
 */
@property (nonatomic , assign , getter=isvip) BOOL vip;

+(instancetype)friendWithDict:(NSDictionary *)dict;
-(instancetype)initWithDict:(NSDictionary *)dict;

+(instancetype)friendWithDict:(NSDictionary *)dict{

       return  [[self alloc]initWithDict:dict];
}

-(instancetype)initWithDict:(NSDictionary *)dict{
    if (self = [super init]) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}
#import <UIKit/UIKit.h>
@class JFFriendGroup, JFHeaderView;

/**
 *  定义代理一般以控件名字家delegate,这是规范
 */
@protocol JFHeaderViewDelegate <NSObject>
@optional
-(void)headerViewDidClick:(JFHeaderView*)view;

@end

@interface JFHeaderView : UITableViewHeaderFooterView

+(instancetype)headerViewWithTableView:(UITableView * )tableView;

@property(nonatomic, strong)JFFriendGroup *group;
/**
 *  这里用id类型是返回任意类型,不依赖任何一个类
 *  也就是在任何一个类里面都可以使用
 */
@property (nonatomic, weak)id<JFHeaderViewDelegate>delegate;
#import "JFHeaderView.h"
#import "JFFriendGroup.h"
#define WIDTH  (self.frame.size.width)
#define HEIGHT  (self.frame.size.height)


@interface JFHeaderView ()
@property(nonatomic, weak)UILabel *countView;
@property(nonatomic, weak)UIButton *nameView;

@end
@implementation JFHeaderView

+(instancetype)headerViewWithTableView:(UITableView * )tableView{
    static NSString *headId = @"headId";
    JFHeaderView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headId];
    if (headerView == nil) {
        headerView = [[JFHeaderView alloc]initWithReuseIdentifier:headId];
    }
    return headerView;

}


/**
 *  在这个初始化方法中,JFHeaderView的frame\bounds没有值
 */
-(id)initWithReuseIdentifier:(NSString *)reuseIdentifier{
    if (self = [super init]) {
        //添加子控件
        //1.添加按钮
        UIButton *nameView = [UIButton buttonWithType:UIButtonTypeCustom];
        [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal];
        [nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted];
        //设置箭头
        [nameView setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal];
        [nameView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        //内容左对齐
        nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        //设置按钮的内边距
        nameView.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
        nameView.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
        [nameView addTarget:self action:@selector(nameViewClick) forControlEvents:UIControlEventTouchUpInside];
        [self.contentView addSubview:nameView];
        self.nameView = nameView;
        //2.添加好友数
        UILabel *countView = [[UILabel alloc]init];
        countView.textAlignment = NSTextAlignmentRight;
        countView.textColor = [UIColor grayColor];
        [self.contentView addSubview:countView];
        self.countView =  countView;
    }
    return  self;

}
/**
 *  当一个控件的frame发生改变时就会调用
 *  一般在这里布局内部的子控件(设置子控件的freme)
 */
-(void)layoutSubviews{

    //注:这个地方一定要调用父类的方法
    [super layoutSubviews];

    //1.设置按钮的freme
    self.nameView.frame = self.bounds;
    //2.设置好友数的frame
    CGFloat countY = 0;
    CGFloat countH =  HEIGHT;
    CGFloat countW = 150;
    CGFloat countX = WIDTH - 10 - countW;
    self.countView.frame = CGRectMake(countX, countY, countW, countH);


}


-(void)setGroup:(JFFriendGroup *)group{
    _group = group;
    //1.设置组名
    [self.nameView setTitle:group.name forState:UIControlStateNormal];
    //2.设置好友数(在线数/总数)
    self.countView.text = [NSString stringWithFormat:@"%d/%lu",group.online,(unsigned long)group.friends.count];;

}


-(void)nameViewClick{
    //1.修改模型标记(状态取反)
    self.group.opened = !self.group.isOpened;
    if ([self.delegate respondsToSelector:@selector(headerViewDidClick:)]) {
        [self.delegate headerViewDidClick:self];
    }

}
/**
 *  但一个控件被添加到控件的时候会调用
 */
-(void)didMoveToSuperview{
    if (self.group.opened) {
        self.nameView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
    }else{
        self.nameView.imageView.transform = CGAffineTransformMakeRotation(0);

    }
}

以上是部分代码,有问题的可以关注我然后提出来我们一起探讨
祝好:2015 - 08 - 09 22 - 53。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值