iOS开发项目篇

QQ列表

2019-03-07  本文已影响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

附二:@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和其子类

上一篇下一篇

猜你喜欢

热点阅读