美文网首页程序员
iOS 关于UITableViwe的继承和mvc的一些简单操作

iOS 关于UITableViwe的继承和mvc的一些简单操作

作者: RogueYBJ | 来源:发表于2018-05-18 21:39 被阅读0次

    首先对于一个小白来说有好多代码都是来自一些网上的大神级别的人物写出来的,现在也有差不多一年了,关于一些代码没有还是有一点自己的看法,把这些代码贴出来就是想与各位朋友们一起探讨探讨,这些代码写出来不知道有没有大仙能够指点一二,好了,差不多了,步入正题吧 👇。

    一、UITableView的继承
    首先我们在ViewController里面写下一个tableView并且正常开局(签订协议以及创建tableView和dataSource的属性)因为我们要继承tableView就要知道一些自己的需求以及需要更改的地方。

    1.首先我们继承之后要可以改变UITableView的Style,因为在创建的时候就需要给出一个Style,不能够通过其他手段进行改变其Style,这样我们应该如何去处理这个问题呢!贴上代码(父类代码) :

    //在这里用一个开关来控制tableView的Style,初始为NO:style:UITableViewStylePlain。
    -(BOOL)isStyle{
        return NO;
    }
    -(UITableView *)tableView{
        if (!_tableView) {
            //判断开关,确定风格。
            if ([self isStyle]) {
                //分组表格
                _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight) style:UITableViewStyleGrouped];
            }else{
                //一组表格
                _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight) style:UITableViewStylePlain];
            }
        }
        return _tableView;
    }
    //同样:我们在返回numberOfSectionsInTableView和numberOfRowsInSection时也要进行判断或者说你的数据源可以写成UITableViewStyleGrouped
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        if ([self isStyle]) {
            return self.dataSource.count;
        }
        return 1;
    }
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        if ([self isStyle]) {
            return 1;
        }
        return self.dataSource.count;
    }
    

    好了当我们创建好tableView后我们要把一些需要添加的东西放在viewDidLoad中添加。
    在继承后如果我们需要更改风格只需要进行重写开关(子类代码):

    //注意这里的重写在你的继承之后的里面写,返回YES:style:UITableViewStyleGrouped。
    -(BOOL)isStyle{
        return YES;
    }
    

    至于添加刷新加载以及头部尾部以及所有的协议方法都可以在继承后做这些操作,你也可以在你的父类里面添加,在父类中添加后也可以在子类中进行更改,是不是方便了很多!

    2、其次,我们要进行数据源(dataSource)的操作,一般来说都是数据请求后添加到dataSource中,我们在请求的过程中让子类告诉父类我们的是get请求还是post请求,并且传输我们的接口给它,我们就是要进行传数据,我们用数组的方式进行传值,至于怎么传值还是和刚才一样在你需要改变的地方给他一个返回值方法,看代码(父类):(也可以通过其他方式进行数据请求)。

    //这里可以传输数据请求需要的东西,可以在子类里面重写。
    -(NSArray *)requestArr{
        //1.给它一个get or post 或者其他类新的
        //2.给它请求的接口
        //3.你想要传的东西
        return @[@"get",@"https://www.jianshu.com/u/aff4c4fbd8db"];
    }
    //在这里进行数据处理,获取你想要的数组,可以在子类里面重写
    -(NSArray *)dataArr:(NSDictionary*)dic{
        NSArray * dataArr = [dic objectForKey:@"Indexes"];
        return dataArr;
    }
    -(void)AFNetWorkingData{
        AFHTTPSessionManager* manager=[AFHTTPSessionManager manager];
        manager.responseSerializer=[AFHTTPResponseSerializer serializer];
      //在这里判断get or post
        if ([[self requestArr][0] isEqualToString:@"get"]) {
            //这里的接口冲数组中获取
            [manager GET:[self requestArr][1] parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                NSLog(@"get数据请求成功!");
                //这里我们json转化为字典
                NSDictionary* jsonDic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
                //然后用一个方法对这个字典进行操作,最终返回出我们需要的数组并且保存到model中赋值给dataSource,再刷新tableView。
                NSMutableArray *muArray = [NSMutableArray array];
                [[self dataArr:jsonDic] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                    [muArray addObject:[ViewModel feedWithDictionary:obj]];
                }];
                self.dataSource = muArray;
                [self.tableView reloadData];
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                NSLog(@"error==%@",error);
            }];
        }else{
              //post请求,请自行操作。
        }
    }
    

    ps:数据请求可能存在差异,请看仔细!
    重写的方法还是就不放上来了,👆讲过了怎么用。

    3、现在tableView和dataSource都有了我们进行cell就要把dataSource带入cell了。
    在这里我用的是Masonry(xib的话还需等待的下一条上传🙂!)
    至于cell没什么太多的的东西正常开局就好了,Masonry与cell和tableView的连接怕大家不会我就把代码贴上来吧👇

    - (void)viewDidLoad {
        [self.tableView registerClass:[ViewCell class] forCellReuseIdentifier:@"cell"];
    }
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        ViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
        //我们在获取dataSource里数据是要判断tableView的Style
        cell.model = self.YBJDataSource[[self isStyle]?indexPath.section:indexPath.row];
        return cell;
    }
    

    cell

    cell.h
    @property(nonnull ,nonatomic ,strong)ViewModel * model;
    
    cell.m
    //要显示在cell上的view
    @property(nonatomic ,nonnull ,strong)ViewView * viewView;
    
    -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
        if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
            [self creatView];//创建子试图
            [self creatStly];//子试图布局
        }
        return self;
    }
    -(void)creatView{
        
        self.viewView = [[ViewView alloc]init];
        [self addSubview:self.viewView];
        
    }
    -(void)creatStly{
        
        [self.viewView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(@5);
            make.bottom.equalTo(@-5);
            make.left.equalTo(@5);
            make.right.equalTo(@-5);
        }];
        
    }
    
    -(void)setModel:(ViewModel *)model{
        _model = model;
        
        self.viewView.model = model;
    }
    

    ps:上面出现了一下吗MVC的代码,请耐心看完!
    嘘......长舒一口气,总算是完成了第一步这些继承的东西,写的都是一些菜鸟代码,希望各路大神给予批评和指导(注意:批评完记得指导一下me🙂!)。
    好了,是时候开始第二步了MVC的操作了,这里面会出现一些界面的传值看字了咯!gogogo👇!

    一、UITableView的MVC
    首先提示一下各位朋友,看不明白可以先去看看MVC的详解。好了,我们先创建一个model和View把model里面的数据进行处理后传给View,然后在View中进行布局传给cell

    1.model在.h文件中根据自己的需要创建出自己想要的东西,然后在.m文件中进行数据的处理,代码如下👇。

    model.h
    
    #import <Foundation/Foundation.h>
    @interface ViewModel : NSObject
    @property(copy ,nonatomic)NSString * TitleStr;
    @property(copy ,nonatomic)NSString * TextStr;
    @property(copy ,nonatomic)NSString * ImageStr;
    @property(assign ,nonatomic)CGSize ImageSize;
    @property(copy ,nonatomic)NSString * TimeStr;
    + (instancetype) feedWithDictionary:(NSDictionary *) dictionary;
    @end
    
    model.m
    
    #import "ViewModel.h"
    
    @implementation ViewModel
    + (instancetype) feedWithDictionary:(NSDictionary *) dictionary{
        
        return [[self alloc]initWithDictionary:dictionary];
    }
    - (instancetype) initWithDictionary:(NSDictionary *) dictionary{
        
        self = [super init];
        
        if (self) {
            
            self.TitleStr = [dictionary objectForKey:@"title"];
            self.TextStr = [[dictionary objectForKey:@"text"] stringByReplacingOccurrencesOfString:@"<br />" withString:@""];
            self.ImageStr = [dictionary objectForKey:@"img"];
            
            [self isFileExist: [dictionary objectForKey:@"img"]];
            self.ImageSize = [UIImage getImageSizeWithURL:[dictionary objectForKey:@"img"]];
            self.TimeStr = [dictionary objectForKey:@"ct"];
        }
        
        return self;
    }
    

    ps:上面的代码里面根据自己的需求填写。

    2.因为我们继承了父类我们的cell又是固定了View,这样的话我们就必须要在View里面进行一些不一样的操作了,为了让这个tableView在所有的界面都可以使用,我们肯定是要让我们的子类改变View的布局。首先创建一个枚举,这里使用全局,我们有几种View风格,就创建几个枚举成员,再利用本地保存将这些进行枚举传值,在这里我用NSUserDefaults进行传值。
    好了接下来我们先创建枚举,代码如下👇:

    //定义枚举类型
    typedef NS_ENUM(NSInteger, ViewViewMasonryStyle)
    {
        ViewViewMasonryStyleNone = 0,
        ViewViewMasonryStyleFirst,
        ViewViewMasonryStyleSecond,
        ViewViewMasonryStyleThree
    };
    //这里我定义了四种类型的枚举
    
    

    再创建NSUserDefaults进行传值,在这里我用了全局的方法存取值

    +(NSUserDefaults*)ViewStyle_NSUserDefaults{
        NSUserDefaults *ViewStyle = [NSUserDefaults standardUserDefaults];
        return ViewStyle;
    }
    +(void)ViewStyle_setObject:(NSString *)Style{
        [[PublicVoid ViewStyle_NSUserDefaults] setObject:Style forKey:@"Style"];
    }
    +(NSString *)ViewStyle_objectForKey{
        return [[PublicVoid ViewStyle_NSUserDefaults] objectForKey:@"Style"];
    }
    

    现在我们要把我们需要什么样风格的View传给View就需要在子类里面进行传值,因为父类只用来继承不用做操作,只能在子类里面更改我们的风格,我们要在子类里面进行更改风格,在viewDidLoad为NSUserDefaults存值,代码如下👇:

    - (void)viewDidLoad {
        [super viewDidLoad];
        [PublicVoid ViewStyle_setObject:@"0"];
    }
    

    传值之后我们要在View中取出NSUserDefaults里面的值并且进行一系列的布局,代码如下👇:

    View.h
    
    #import <UIKit/UIKit.h>
    #import "ViewModel.h"
    
    @interface ViewView : UIView
    
    @property(nonnull ,nonatomic ,strong)ViewModel * model;
    
    @end
    
    view.m
    //这些事属性
    //标题
    @property(nonnull,nonatomic,strong)UILabel * TitleLabel;
    //文本
    @property(nonnull,nonatomic,strong)UILabel * TextLabel;
    //图像
    @property(nonnull,nonatomic,strong)UIImageView * ImageView;
    //图像大小
    @property(nonatomic,assign)CGSize ImageSize;
    //时间
    @property(nonnull,nonatomic,strong)UILabel * TimeLabel;
    
    //init方法
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            self.layer.cornerRadius = 0.0;
            self.layer.masksToBounds = YES;
            //边框宽
            self.layer.borderWidth = 1;
            //边框颜色
            self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
            //取值并且创建子控间以及子控间的布局
            [self createUIStyle:[[PublicVoid ViewStyle_objectForKey] integerValue]];
        }
        return self;
    }
    //创建子控间以及子控间的布局
    -(void)createUIStyle:(ViewViewMasonryStyle)Style{
        switch (Style) {
            case ViewViewMasonryStyleNone:
                [self createTitleLabel];//TitleLabel创建
                [self createTextLabel];//TextLabel创建
                [self createTimeLabel];//TimeLabel创建
                [self setViewAtuoLayoutNone];//第一种布局
                break;
            case ViewViewMasonryStyleFirst:
                [self createTitleLabel];//TitleLabel创建
                [self createImageView];//ImageView创建
                [self createTimeLabel];//TimeLabel创建
                [self setViewAtuoLayoutFirst];//第二种布局
                break;
            case ViewViewMasonryStyleSecond:
                [self setViewAtuoLayoutSecond];//没用到
                break;
            case ViewViewMasonryStyleThree:
                [self setViewAtuoLayoutThree];//没用到
                break;
                
            default:
                break;
        }
    }
    //赋值
    -(void)setModel:(ViewModel *)model{
        self.TitleLabel.text = model.TitleStr;
        [self.ImageView sd_setImageWithURL:[NSURL URLWithString:model.ImageStr] placeholderImage:[UIImage sd_gifImage:@"JZZ"] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
            NSLog(@"加载成功!");
        }];
        self.TextLabel.text = model.TextStr;
        self.TimeLabel.text = model.TimeStr;
        self.ImageSize = model.ImageSize;
    }
    //子试图
    -(void)createTitleLabel{
        //标题
        self.TitleLabel = [[UILabel alloc]init];
        self.TitleLabel.font = [UIFont systemFontOfSize:15];
        self.TitleLabel.textColor = [UIColor orangeColor];
        self.TitleLabel.textAlignment = 1;
        [self addSubview:self.TitleLabel];
    }
    -(void)createImageView{
        //图像
        self.ImageView = [[UIImageView alloc]init];
        self.ImageView.layer.cornerRadius = 3.0;
        self.ImageView.layer.masksToBounds = YES;
        [self addSubview:self.ImageView];
    }
    -(void)createTextLabel{
        //文本
        self.TextLabel = [[UILabel alloc]init];
        self.TextLabel.font = [UIFont systemFontOfSize:15];
        self.TextLabel.textColor = [UIColor blackColor];
        self.TextLabel.numberOfLines = 0;
        [self.TextLabel sizeToFit];
        [self addSubview:self.TextLabel];
    }
    -(void)createTimeLabel{
        //时间
        self.TimeLabel = [[UILabel alloc]init];
        self.TimeLabel.font = [UIFont systemFontOfSize:15];
        self.TimeLabel.textColor = [UIColor blackColor];
        self.TimeLabel.textAlignment = 2;
        [self addSubview:self.TimeLabel];
    }
    
    //布局一
    //ViewViewMasonryStyleNone布局
    -(void)setViewAtuoLayoutNone{
        
        [self.TitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(@5);
            make.left.equalTo(@10);
            make.right.equalTo(@(-10));
            make.height.equalTo(@30);
        }];
        [self.TextLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.TitleLabel.mas_bottom).with.offset(5);
            make.bottom.equalTo(self.TimeLabel.mas_top).with.offset(5);
            make.left.equalTo(@10);
            make.right.equalTo(@(-10));
        }];
        [self.TimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.bottom.equalTo(@(-5));
            make.left.equalTo(@10);
            make.right.equalTo(@(-10));
            make.height.equalTo(@30);
        }];
        
    }
    //布局二
    //ViewViewMasonryStyleFirst布局
    -(void)setViewAtuoLayoutFirst{
        //在这里进行第二种布局,要注意第二种风格添加了几个控件
    }
    

    做完这些是不是感觉子类里面基本上都没有代码了,非常凉凉。

    哎呀我去,这就过去一下午了码这么多字真辛苦,总算是说完了,最后总结一下:
    在这里面存在一些小的缺陷,不过不足以影响整个大局。
    缺陷:
    1.View太过膨胀。
    解决方案:可以每创建一个子类创建一个View。
    2.model里面还需要更改接口调用的参数。
    解决方案:可以每创建一个子类传一次参数。
    3.tableView里同时存在section and row。
    解决方案:可以在返回Style的时候做一下更改,或者在收数据的时候做一些变化。
    有没有感觉非常的方便!
    最后:
    首先是要感谢一下看了这么久的朋友们!
    很开心和大家分享我的这些东西!
    这也是我的处女作了!
    后面还坚持下去!
    Yeah!

    相关文章

      网友评论

        本文标题:iOS 关于UITableViwe的继承和mvc的一些简单操作

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