• 一个架构合理的UITableView应该是如何的?


    原文: http://www.chentoo.com/?p=200


     iOS 开发中,UITableView 应该是最经常使用到的了。完毕一个UITableView应该实现他的DataSource和Delegate来讲数据Model填充进View(Cell)中。大家也是知晓的。可是一个UITableView应该如何才干实现良好的架构,事实上非常多人是不在意的。而这也是一个刚開始学习的人和一个工作多年的人最大的区别。

    一、MVC

    首先我们要谈论的是MVC。这并不奇怪。iOS开发整个的架构体系,就是一个经典的MVC。 Model层负责数据,View层负责展现,Controller层负责协调和处理。而不论你使用UITableViewController 还是 UIViewController中有一个UITableView,你的UITableView 的 DataSource 的几个方法,都应该起到一个Controller的作用。而不应该在其中进行Model层数据的处理,或者View层视图的改动。

    二、改怎么做

    空洞的话说完了,怎么做呢?我们就从头開始实现一个UITableView。新建一个project。DemoTableView改动ViewController.m,给当前视图增加一个UITabelView。

    #import "ViewController.h"
    
    @interface ViewController () <UITableViewDataSource, UITableViewDelegate>
    
    @property (strong, nonatomic) UITableView *tableView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
        _tableView.dataSource = self;
        _tableView.delegate = self;
        [self.view addSubview:self.tableView];
        
    }
    
    @end
    

    假设我们如今尝试执行。肯定是出错的,由于我们没有实现DataSource和Delegate。在实现DataSource之前,让我们先准备号数据源Model。

    2.1 Model

    新建一个Model类:DemoObject。

    它有两个属性title 和 content。


    //
    //  DemoObject.h
    //  DemoTableView
    //
    //  Created by xiazhidi on 15/3/12.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface DemoObject : NSObject
    
    @property (strong, nonatomic) NSString *title;
    @property (strong, nonatomic) NSString *content;
    
    @end
    


    Model层做到这里就完成了,Model的获取,改动什么的都一股脑丢到ViewController里甚至TableView的DateSoucre里进行。可是合理的架构应该是这种。我们应该在Model层封装好全部的数据请求和处理逻辑,而仅仅暴露出获取的接口提供给Controller层使用。

    我们新建一个Category : DemoObject+Api。在这其中封装好Model的获取和处理逻辑。

    //
    //  DemoObject+Api.h
    //  DemoTableView
    //
    //  Created by xiazhidi on 15/3/12.
    //  Copyright (c) 2015年 baixing. All rights reserved.
    //
    
    #import "DemoObject.h"
    
    typedef void(^DemoObjectFetchCompletionBlock)(NSArray *demoObjects, NSError *error);
    
    @interface DemoObject (Api)
    
    + (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock;
    
    @end
    

    能够看到,我们提供了一个类方法暴露给Controller层,让它能够方便的获取数据,数据通过Block返回。当然你也能够用Delegate实现,这个看个人习惯。对应的。.m的实现例如以下:(我们仅仅是造一些假数据,真实应用中肯定要设计从网络获取)

    //
    //  DemoObject+Api.m
    //  DemoTableView
    //
    //  Created by xiazhidi on 15/3/12.
    //  Copyright (c) 2015年 baixing. All rights reserved.
    //
    
    #import "DemoObject+Api.h"
    
    @implementation DemoObject (Api)
    
    + (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock
    {
        NSMutableArray *mArray = [[NSMutableArray alloc] initWithCapacity:10];
        
        for (NSInteger i = 0; i < 10; i++)
        {
            DemoObject *demoObject = [[DemoObject alloc] init];
            demoObject.title = [NSString stringWithFormat:@"这是第%lu个标题", (unsigned long)i];
            demoObject.content = [NSString stringWithFormat:@"这是第%lu个内容", (unsigned long)i];
            [mArray addObject:demoObject];
        }
        
        if (completionBlock)
        {
            completionBlock([mArray copy], nil);
        }
    }
    
    @end
    

    2.2 View

    对于UITableView的View层来说,就是我们要建立一个 Cell ,能够用Xib也能够不用。

    那我们这里就用吧。毕竟正式项目中,autolayout什么的用起来还是方便的。新建DemoTableViewCell,放好两个label,连连线什么的就不讲了。详细可看后面附的源代码。关键是,我们须要在cell中,实现cell的配置逻辑。所以我们建立了一个category

    //
    //  DemoTableViewCell+Configure.h
    //  DemoTableView
    //
    //  Created by xiazhidi on 15/3/12.
    //  Copyright (c) 2015年 baixing. All rights reserved.
    //
    
    #import "DemoTableViewCell.h"
    @class DemoObject;
    
    @interface DemoTableViewCell (Configure)
    
    - (void)configureWithDemoObject:(DemoObject *)demoObject;
    
    @end
    

    //  DemoTableViewCell+Configure.m
    //  DemoTableView
    //
    //  Created by xiazhidi on 15/3/12.
    //  Copyright (c) 2015年 baixing. All rights reserved.
    //
    
    #import "DemoTableViewCell+Configure.h"
    #import "DemoObject.h"
    
    @implementation DemoTableViewCell (Configure)
    
    - (void)configureWithDemoObject:(DemoObject *)demoObject
    {
        self.titleLabel.text = demoObject.title;
        self.contentLabel.text = demoObject.content;
    }
    
    @end
    


    暴露了一个接口给Controller来实现view的配置。 这种长处是,Controller层不会堆积非常多的代码让人头痛(想想一个复杂的cell可能会有多少须要配置的UI元素),而且会非常方便的方便Cell的复用。

    2.3 Controller

    我们再来看看如今Controller层详细实现的代码,层次会十分清晰。



    //
    //  ViewController.m
    //  DemoTableView
    //
    //  Created by xiazhidi on 15/3/12.
    //  Copyright (c) 2015年 baixing. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "DemoObject+Api.h"
    #import "DemoTableViewCell+Configure.h"
    
    @interface ViewController () <UITableViewDataSource, UITableViewDelegate>
    
    @property (strong, nonatomic) UITableView *tableView;
    
    @property (strong, nonatomic) NSArray *demos;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
        _tableView.dataSource = self;
        _tableView.delegate = self;
        [_tableView registerNib:[UINib nibWithNibName:@"DemoTableViewCell" bundle:nil] forCellReuseIdentifier:DemoTableViewCellReuseIdentifier];
        [self.view addSubview:self.tableView];
    
        __weak ViewController *weakSelf = (ViewController *)self;
        
        [DemoObject fetchWithCompletionBlock:^(NSArray *demoObjects, NSError *error) {
            if (!error)
            {
                weakSelf.demos = demoObjects;
                [weakSelf.tableView reloadData];
            }
        }];
    }
    
    #pragma mark - UITableViewDataSource
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.demos.count;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return 60.0f;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DemoTableViewCellReuseIdentifier forIndexPath:indexPath];
        
        [cell configureWithDemoObject:self.demos[indexPath.row]];
        
        return cell;
    }
    
    @end

    三、总结

    以上是一个简单的UITableView的小样例,事实上这样做的目的,就是为了给Controller瘦身,让代码逻辑更清晰。让结构更合理。另外另一些优化的空间,比方把DateSource独立出来成为一个类。这样在Controller其中不在出现DateSource的代码,会更加清爽,可是个人喜好,我不是非常喜欢这样做。以上的样例源代码,在以下能够下载。https://github.com/chentoo/DemoTableView    
  • 相关阅读:
    开发进度二
    开发进度一
    大道至简阅读笔记01
    用户模板和用户评价
    第九周总结
    第八周总结
    NABCD项目分析
    第七周总结
    第六周总结
    构建之法阅读笔记03
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6783016.html
Copyright © 2020-2023  润新知