QQ列表

作者: 小石头呢 | 来源:发表于2019-03-07 08:15 被阅读24次

    源代码:

    链接:
    链接:
    https://pan.baidu.com/s/1KgLCWEps3pMJnIzm1ZArpg 密码:h16b

    主要代码:

    //
    //  ViewController.m
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/1.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "GroupModel.h"
    #import "FriendModel.h"
    #import "MJExtension.h"
    #import "FriendTableViewCell.h"
    #import "HeaderInSection.h"
    
    @interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
    
    /**保存所有小组的信息*/
    @property (nonatomic,strong) NSMutableArray *groupModelsArray;
    
    /**UITableView的属性变量*/
    @property (weak, nonatomic) IBOutlet UITableView *tableView;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSLog(@"%@",self.groupModelsArray);
    }
    
    
    #pragma mark -------lazyLoad ---------
    //groupModelsArray的get方法 懒加载
    -(void)manualLoad{
        //获取plist文件路径
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"qq" ofType:@"plist"];
        
        //读取文件的内容
        NSArray *dataArray = [NSArray arrayWithContentsOfFile:filePath];
        
        //解析数据
        self.groupModelsArray = [NSMutableArray array];
        
        for (NSDictionary *gDic in dataArray) {
            
            //创建Group模型
            GroupModel *model = [GroupModel modelWithDic:gDic];
            
            //保存这个小组模型
            [self.groupModelsArray addObject:model];
            
        }
    }
    
    
    -(void)autoLoad{
        //使用开开源库解决
        [GroupModel mj_setupObjectClassInArray:^NSDictionary *{
            
            return  @{
                      @"friends":[FriendModel class],
                      };
        }];
        
        self.groupModelsArray = [GroupModel mj_objectArrayWithFilename:@"qq.plist"];
    }
    
    -(NSMutableArray *)groupModelsArray{
        
        if (_groupModelsArray == nil) {
            
            //手动
            //[self manualLoad];
            
            //自动
            [self autoLoad];
            
        }
        
        return _groupModelsArray;
    }
    
    #pragma mark -------tableView配置 ---------
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        
        //配置TableView显示多少组数据
        return self.groupModelsArray.count;
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        
        //配置每个组有多少行数据
        GroupModel *gModel = [self.groupModelsArray objectAtIndex:section];
        
        if (gModel.status == kGroupStatusOpen) {
            return gModel.friends.count;
        } else{
            return 0;
        }
        
        
    }
    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        
        //配置每行数据内容
        static NSString *cellID = @"cellID";
        
        FriendTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
        
        //获取section对应的row的内容
        
        //1.获取小组信息
        GroupModel *gModel = [self.groupModelsArray objectAtIndex:indexPath.section];
        
        //2.获取小组里面row对应的好友信息
        FriendModel *fModel = [gModel.friends objectAtIndex:indexPath.row];
        
        //3.配置cell
        cell.iconImageView.image = [UIImage imageNamed:fModel.icon];
        cell.nameLabel.text = fModel.name;
        cell.modeLabel.text = fModel.mode;
        
        return cell;
    }
    
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        
        //配置每行数据的高度
        return 80;
    }
    
    
    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
        
        //配置每一个小组的头部内容
        HeaderInSection *hView = [[[NSBundle mainBundle] loadNibNamed:@"HeaderInSection" owner:nil options:nil] firstObject];
        
        GroupModel *gModel = [self.groupModelsArray objectAtIndex:section];
        
        //设置小组的标题
        hView.nameLabel.text = gModel.sectionName;
        
        //判断当前这个箭头的方向
        if (gModel.status == kGroupStatusClose) {
            
            hView.arrowImageView.transform = CGAffineTransformRotate(hView.arrowImageView.transform, -M_PI_2);
        }
        
        //解决block循环引用
        __block typeof(hView) weakSelf = hView;
        
        //接受按钮被点击的事件
        [hView setClickedBlock:^{
            
            CGFloat angle;
            
            //点击之后的事情
            if (gModel.status == kGroupStatusOpen) {
                
                //逆时针旋转90度
                angle = -M_PI_2;
                gModel.status = kGroupStatusClose;
            } else{
                
                //顺时针旋转90度
                angle = M_PI_2;
                gModel.status = kGroupStatusOpen;
            }
            
            //用更新之后的model去替换原来的model,其status属性改变了
            [self.groupModelsArray replaceObjectAtIndex:section withObject:gModel];
            
            //刷新section对应的小组
            NSIndexSet *set = [NSIndexSet indexSetWithIndex:section];
            [self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationFade];
            
            //动画
            [UIView animateWithDuration:0.25 animations:^{
                
                weakSelf.arrowImageView.transform = CGAffineTransformRotate(weakSelf.arrowImageView.transform, angle);
            }];
            
        }];
        
        return hView;
    }
    
    -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
        
        //配置头部视图高度
        return 40;
    }
    
    @end
    
    
    //
    //  GroupModel.h
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/1.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    typedef enum {
        kGroupStatusClose,
        kGroupStatusOpen
    }kGroupStatus;
    
    @interface GroupModel : NSObject
    
    //能被外界访问的数据
    
    /**组名*/
    @property (nonatomic,copy) NSString *sectionName;
    
    /**好友模型数组-手动*/
    @property (nonatomic,strong) NSArray *friendModelsArray;
    
    /**好友模型数组-自动*/
    @property (nonatomic,strong) NSArray *friends;
    
    /**记录小组的状态*/
    @property (nonatomic,assign) kGroupStatus status;
    
    //数据解析
    +(instancetype)modelWithDic:(NSDictionary *)dic;
    
    @end
    
    
    //
    //  GroupModel.m
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/1.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import "GroupModel.h"
    #import "FriendModel.h"
    
    @implementation GroupModel
    
    //数据解析
    +(instancetype)modelWithDic:(NSDictionary *)dic{
        
        //创建GroupModel
        GroupModel *model = [[GroupModel alloc] init];
        model.sectionName = [dic objectForKey:@"sectionName"];
        
        //创建好友的模型数组 外部需要不可变的 用可变的暂时数组代替
        NSMutableArray *tempArray = [NSMutableArray array];
        
        
        //获取好友信息
        NSArray *friends = [dic objectForKey:@"friends"];
        
        //一个一个地解析好友数据
        for (NSDictionary *fDic in friends) {
            
            //创建好友的模型对象
            FriendModel *fModel = [FriendModel new];
            [fModel setValuesForKeysWithDictionary:fDic];
            
            //保存这个模型 --- 添加到数组中
            [tempArray addObject:fModel];
            
        }
        
        //将暂时的数组赋给好友的模型数组
        model.friendModelsArray = tempArray;
        
        return model;
    }
    
    @end
    
    
    //
    //  FriendModel.h
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/1.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface FriendModel : NSObject
    
    //能被外界访问的数据
    
    /**头像*/
    @property (nonatomic,copy) NSString *icon;
    
    /**名称*/
    @property (nonatomic,copy) NSString *name;
    
    /**动态*/
    @property (nonatomic,copy) NSString *mode;
    
    @end
    
    
    //
    //  FriendModel.m
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/1.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import "FriendModel.h"
    
    @implementation FriendModel
    
    @end
    
    
    //
    //  FriendTableViewCell.h
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/2.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface FriendTableViewCell : UITableViewCell
    
    /**cell显示的头像图片*/
    @property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
    
    /**cell上显示的名字*/
    @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    
    /**cell上显示的动态内容*/
    @property (weak, nonatomic) IBOutlet UILabel *modeLabel;
    
    @end
    
    
    //
    //  FriendTableViewCell.m
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/2.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import "FriendTableViewCell.h"
    
    @implementation FriendTableViewCell
    
    - (void)awakeFromNib {
        [super awakeFromNib];
        // Initialization code
    }
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
        [super setSelected:selected animated:animated];
    
        // Configure the view for the selected state
    }
    
    @end
    
    
    //
    //  HeaderInSection.h
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/2.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    typedef void (^headerButtonClicked)(void);
    
    @interface HeaderInSection : UIView
    
    /**旋转视图*/
    @property (weak, nonatomic) IBOutlet UIImageView *arrowImageView;
    
    /**组名*/
    @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    
    /**定义一个block属性变量*/
    @property (nonatomic,copy) headerButtonClicked clickedBlock;;
    
    @end
    
    
    
    //
    //  HeaderInSection.m
    //  QQ列表
    //
    //  Created by 许磊 on 2019/3/2.
    //  Copyright © 2019年 xulei. All rights reserved.
    //
    
    #import "HeaderInSection.h"
    
    @implementation HeaderInSection
    
    - (IBAction)headerButtonDidClicked:(UIButton *)sender {
        
        //回调按钮被点击的事件
        self.clickedBlock();
    }
    
    
    @end
    

    运行结果

    运行结果

    开发步骤

    1.处理数据转模型
    2.自定义Cell
    3.sectionheader视图

    附一:UITableView

    • 1.UITableView数据的显示通过Delegate和DataSource来配置(NSIndexPath:section row)

    • 2.UITableView的类型 plain和grouped类型

    • 3.UITableView的重复利用机制

    • 4.UITableViewCell的类型 Default value1 value2 subtitle

    • 5.自己创建UITableViewCell
      a.在创建cell的同时手动添加控件 使用tag来获取这个控件
      b.创建一个类继承于UITableViewCell封装Cell的布局
      c.xib自定义Cell
      d.storyboard自定义Cell,前提是控制器在storyboard里面

    • 6.UITableView刷新数据
      a.使用数组保存资源
      b.reloadData

    • 7.数据封装为一个模型
      a. 用一个类来描述一条数据
      b. 访问方便 减少代码的冗余

    附二:@property 属性类型归纳和介绍

    1.atomic:原子操作 给资源加锁解锁 安全 效率不高

    2.nonatomic:非原子操作 没有加锁解锁机制 不安全 效率高

    3.strong:强引用 声明对不是自己创建的对象的拥有权 reatinCount+1 OC的对象类型就用它 针对 @property

    4.retain:和strong相同,除了@property 关键字以外,在代码里面也需要声明拥有权 reatinCount+1

    5.copy:拷贝一份 不是所有的对象类型都可以使用 自己创建的对象必须服从NSCopy协议才能使用 修饰NSString和block一般只用copy

    6.弱引用: 只是定义了某一个类型的对象 不会对这个对象声明拥有权(不引用)

    7.readwrite:可读可写(默认) 提供了set,get方法

    8.readonly:只读 只提供get方法

    9.assign:修饰C语言的基本数据类型 为了防止循环引用delegate

    1.atomic与nonatomic
    atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题
    nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。

    2.readwrite与readonly(readwrite、readonly这两个属性的真正价值,不是提供成员变量访问接口,而是控制成员变量的访问权限)
    readwrite:这个属性是默认的情况,会自动为你生成存取器。
    readonly:只生成getter不会有setter方法。

    3.strong与weak(strong与retain功能相似;weak与assign相似,只是当对象消失后weak会自动把指针变为nil;)
    strong:强引用,也是我们通常说的引用,其存亡直接决定了所指向对象的存亡。如果不存在指向一个对象的引用,并且此对象不再显示在列表中,则此对象会被从内存中释放。
    weak:弱引用,不决定对象的存亡。即使一个对象被持有无数个弱引用,只要没有强引用指向它,那么还是会被清除。

    4.assign、copy、retain
    assign:默认类型,setter方法直接赋值,不进行任何retain操作,不改变引用计数。一般用来处理基本数据类型。
    retain:释放旧的对象(release),将旧对象的值赋给新对象,再令新对象引用计数为1。我理解为指针的拷贝,拷贝一份原来的指针,释放原来指针指向的对象的内容,再令指针指向新的对象内容。
    copy:与retain处理流程一样,先对旧值release,再copy出新的对象,retainCount为1.为了减少对上下文的依赖而引入的机 制。我理解为内容的拷贝,向内存申请一块空间,把原来的对象内容赋给它,令其引用计数为1。对copy属性要特别注意:被定义有copy属性的对象必须要 符合NSCopying协议,必须实现- (id)copyWithZone:(NSZone *)zone方法。
    也可以直接使用:
    使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
    使用copy: 对NSString
    使用retain: 对其他NSObject和其子类

    相关文章

      网友评论

        本文标题:QQ列表

        本文链接:https://www.haomeiwen.com/subject/kjrtuqtx.html