zoukankan      html  css  js  c++  java
  • 用适配器模式处理复杂的UITableView中cell的业务逻辑

    用适配器模式处理复杂的UITableView中cell的业务逻辑

    适配器是用来隔离数据源对cell布局影响而使用的,cell只接受适配器的数据,而不会与外部数据源进行交互.

    源码:

    ModelCell.h 与 ModelCell.m

    //
    //  ModelCell.h
    //  Adapter
    //
    //  Created by XianMingYou on 15/2/10.
    //  Copyright (c) 2015年 XianMingYou. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    #define NAME_FRAME  CGRectMake(15, 15, 290, 20)
    #define NAME_FONT   [UIFont boldSystemFontOfSize:18.f]
    
    #define ADDRESS_FRAME CGRectMake(15, 15 + 30, 290, 20)
    #define ADDRESS_FONT  [UIFont systemFontOfSize:14.f]
    
    #define DESCRIBE_FRAME CGRectMake(15, 15 + 60, 290, 20)
    #define DESCRIBE_FONT  [UIFont italicSystemFontOfSize:14.f]
    
    @interface ModelCell : UITableViewCell
    
    /**
     *  适配器处理逻辑的地方
     *
     *  @param adapter 适配器
     */
    - (void)accessModelAdapter:(id)adapter;
    
    @end
    //
    //  ModelCell.m
    //  Adapter
    //
    //  Created by XianMingYou on 15/2/10.
    //  Copyright (c) 2015年 XianMingYou. All rights reserved.
    //
    
    #import "ModelCell.h"
    #import "ModelAdapter.h"
    #import "UIView+SetRect.h"
    
    @interface ModelCell ()
    
    @property (nonatomic, strong) UILabel *name;          // 名字
    @property (nonatomic, strong) UILabel *address;       // 地址
    @property (nonatomic, strong) UILabel *describeInfo;  // 描述信息
    
    @end
    
    @implementation ModelCell
    
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
        if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
            [self createView];
        }
        
        return self;
    }
    
    - (void)createView {
        self.name                   = [[UILabel alloc] initWithFrame:NAME_FRAME];
        self.name.font              = NAME_FONT;
        self.name.numberOfLines     = 0.f;
        self.name.textColor         = [UIColor redColor];
        [self addSubview:self.name];
        
        self.address                   = [[UILabel alloc] initWithFrame:ADDRESS_FRAME];
        self.address.font              = ADDRESS_FONT;
        self.address.numberOfLines     = 0.f;
        [self addSubview:self.address];
        
        self.describeInfo                   = [[UILabel alloc] initWithFrame:DESCRIBE_FRAME];
        self.describeInfo.font              = DESCRIBE_FONT;
        self.describeInfo.numberOfLines     = 0.f;
        self.describeInfo.textColor         = [UIColor grayColor];
        self.describeInfo.textAlignment     = NSTextAlignmentRight;
        [self addSubview:self.describeInfo];
    }
    
    - (void)accessModelAdapter:(id)adapter {
        
        ModelAdapter *dataAdapter = adapter;
        
        self.name.text         = dataAdapter.name;
        self.name.frame        = NAME_FRAME;
        [self.name sizeToFit];
        
        self.address.text      = dataAdapter.address;
        self.address.frame     = ADDRESS_FRAME;
        [self.address sizeToFit];
        
        self.describeInfo.text  = dataAdapter.describeInfo;
        self.describeInfo.frame = DESCRIBE_FRAME;
        [self.describeInfo sizeToFit];
        self.describeInfo.x     = 320 - self.describeInfo.width - 10;
        
        self.address.y      = NAME_FRAME.origin.y + dataAdapter.nameHeight;
        self.describeInfo.y = self.address.y + dataAdapter.addressHeight;
    }
    
    @end

    ModelAdapter.h 与 ModelAdapter.m

    //
    //  ModelAdapter.h
    //  Adapter
    //
    //  Created by XianMingYou on 15/2/10.
    //  Copyright (c) 2015年 XianMingYou. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface ModelAdapter : NSObject
    
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, strong) NSString *address;
    @property (nonatomic, strong) NSString *describeInfo;
    
    // 初始化适配器
    - (instancetype)initWithData:(id)data;
    
    #pragma mark 只读属性
    @property (nonatomic, readonly) CGFloat nameHeight;
    @property (nonatomic, readonly) CGFloat addressHeight;
    @property (nonatomic, readonly) CGFloat describeInfoHeight;
    @property (nonatomic, readonly) CGFloat totalHeight;
    
    @end

    设置frame值用的类

    UIView+SetRect.h 与 UIView+SetRect.m

    //
    //  UIView+SetRect.h
    //  TestPch
    //
    //  Created by YouXianMing on 14-12-26.
    //  Copyright (c) 2014年 YouXianMing. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface UIView (SetRect)
    
    // Frame
    @property (nonatomic) CGPoint viewOrigin;
    @property (nonatomic) CGSize  viewSize;
    
    // Frame Origin
    @property (nonatomic) CGFloat x;
    @property (nonatomic) CGFloat y;
    
    // Frame Size
    @property (nonatomic) CGFloat width;
    @property (nonatomic) CGFloat height;
    
    // Frame Borders
    @property (nonatomic) CGFloat top;
    @property (nonatomic) CGFloat left;
    @property (nonatomic) CGFloat bottom;
    @property (nonatomic) CGFloat right;
    
    // Center Point
    #if !IS_IOS_DEVICE
    @property (nonatomic) CGPoint center;
    #endif
    @property (nonatomic) CGFloat centerX;
    @property (nonatomic) CGFloat centerY;
    
    // Middle Point
    @property (nonatomic, readonly) CGPoint middlePoint;
    @property (nonatomic, readonly) CGFloat middleX;
    @property (nonatomic, readonly) CGFloat middleY;
    @property (nonatomic, assign) CGFloat cornerRadius ;
    @property (nonatomic ,assign) BOOL round ;
    @end
    //
    //  UIView+SetRect.m
    //  TestPch
    //
    //  Created by YouXianMing on 14-12-26.
    //  Copyright (c) 2014年 YouXianMing. All rights reserved.
    //
    
    #import "UIView+SetRect.h"
    
    @implementation UIView (SetRect)
    
    #pragma mark Frame
    
    - (CGPoint)viewOrigin
    {
        return self.frame.origin;
    }
    
    - (void)setViewOrigin:(CGPoint)newOrigin
    {
        CGRect newFrame = self.frame;
        newFrame.origin = newOrigin;
        self.frame = newFrame;
    }
    
    - (CGSize)viewSize
    {
        return self.frame.size;
    }
    
    - (void)setViewSize:(CGSize)newSize
    {
        CGRect newFrame = self.frame;
        newFrame.size = newSize;
        self.frame = newFrame;
    }
    
    
    #pragma mark Frame Origin
    
    - (CGFloat)x
    {
        return self.frame.origin.x;
    }
    
    - (void)setX:(CGFloat)newX
    {
        CGRect newFrame = self.frame;
        newFrame.origin.x = newX;
        self.frame = newFrame;
    }
    
    - (CGFloat)y
    {
        return self.frame.origin.y;
    }
    
    - (void)setY:(CGFloat)newY
    {
        CGRect newFrame = self.frame;
        newFrame.origin.y = newY;
        self.frame = newFrame;
    }
    
    
    #pragma mark Frame Size
    
    - (CGFloat)height
    {
        return self.frame.size.height;
    }
    
    - (void)setHeight:(CGFloat)newHeight
    {
        CGRect newFrame = self.frame;
        newFrame.size.height = newHeight;
        self.frame = newFrame;
    }
    
    - (CGFloat)width
    {
        return self.frame.size.width;
    }
    
    - (void)setWidth:(CGFloat)newWidth
    {
        CGRect newFrame = self.frame;
        newFrame.size.width = newWidth;
        self.frame = newFrame;
    }
    
    
    #pragma mark Frame Borders
    
    - (CGFloat)left
    {
        return self.x;
    }
    
    - (void)setLeft:(CGFloat)left
    {
        self.x = left;
    }
    
    - (CGFloat)right
    {
        return self.frame.origin.x + self.frame.size.width;
    }
    
    - (void)setRight:(CGFloat)right
    {
        self.x = right - self.width;
    }
    
    - (CGFloat)top
    {
        return self.y;
    }
    
    - (void)setTop:(CGFloat)top
    {
        self.y = top;
    }
    
    - (CGFloat)bottom
    {
        return self.frame.origin.y + self.frame.size.height;
    }
    
    - (void)setBottom:(CGFloat)bottom
    {
        self.y = bottom - self.height;
    }
    
    
    #pragma mark Center Point
    
    #if !IS_IOS_DEVICE
    - (CGPoint)center
    {
        return CGPointMake(self.left + self.middleX, self.top + self.middleY);
    }
    
    - (void)setCenter:(CGPoint)newCenter
    {
        self.left = newCenter.x - self.middleX;
        self.top = newCenter.y - self.middleY;
    }
    #endif
    
    - (CGFloat)centerX
    {
        return self.center.x;
    }
    
    - (void)setCenterX:(CGFloat)newCenterX
    {
        self.center = CGPointMake(newCenterX, self.center.y);
    }
    
    - (CGFloat)centerY
    {
        return self.center.y;
    }
    
    - (void)setCenterY:(CGFloat)newCenterY
    {
        self.center = CGPointMake(self.center.x, newCenterY);
    }
    
    
    #pragma mark Middle Point
    
    - (CGPoint)middlePoint
    {
        return CGPointMake(self.middleX, self.middleY);
    }
    
    - (CGFloat)middleX
    {
        return self.width / 2;
    }
    
    - (CGFloat)middleY
    {
        return self.height / 2;
    }
    
    - (void)setCornerRadius:(CGFloat)cornerRadius
    {
        self.layer.masksToBounds = YES ;
        self.layer.cornerRadius = cornerRadius ;
    }
    
    - (void)setRound:(BOOL)round
    {
        [self setCornerRadius:self.height/2];
    }
    
    - (CGFloat)cornerRadius
    {
        return  self.layer.cornerRadius ;
    }
    
    - (BOOL)round
    {
        return NO ;
    }
    
    @end

    控制器源码:

    //
    //  ViewController.m
    //  Adapter
    //
    //  Created by XianMingYou on 15/2/10.
    //  Copyright (c) 2015年 XianMingYou. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "ModelCell.h"
    #import "ModelAdapter.h"
    
    #define REUSE_MODEL_CELL  @"ModelCell"
    
    @interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
    
    @property (nonatomic, strong) UITableView  *tableView;
    @property (nonatomic, strong) NSArray      *dataArray;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // 创建数据源
        [self createDataSource];
        
        // 创建tableView
        [self createTableView];
    }
    
    #pragma mark - 数据源
    - (void)createDataSource {
        ModelAdapter *data1 = [[ModelAdapter alloc] initWithData:@{@"name"         : @"YouXianMing",
                                                                   @"address"      : @"北京通州区果园地铁站附近",
                                                                   @"describeInfo" : @"iOS Developer"}];
        ModelAdapter *data2 = [[ModelAdapter alloc] initWithData:@{@"name"         : @"QiuLiang",
                                                                   @"address"      : @"上海浦东XXXX开发园区,德望路园丁小区福星楼7123左侧34桌",
                                                                   @"describeInfo" : @".Net Developer"}];
        ModelAdapter *data3 = [[ModelAdapter alloc] initWithData:@{@"name"         : @"",
                                                                   @"address"      : @"上海浦东XXXX开发园区,德望路园丁小区福星楼7123左侧34桌",
                                                                   @"describeInfo" : @".Net Developer"}];
        ModelAdapter *data4 = [[ModelAdapter alloc] initWithData:@{@"name"         : @"YouXianMing",
                                                                   @"address"      : @"",
                                                                   @"describeInfo" : @"C++ Developer"}];
        self.dataArray = @[data1, data2, data3, data4];
    }
    
    #pragma mark - tableView相关
    - (void)createTableView {
        self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds
                                                      style:UITableViewStylePlain];
        self.tableView.delegate   = self;
        self.tableView.dataSource = self;
        [self.tableView registerClass:[ModelCell class] forCellReuseIdentifier:REUSE_MODEL_CELL];
        [self.view addSubview:self.tableView];
    }
    
    #pragma mark row的数目
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return self.dataArray.count;
    }
    
    #pragma mark 初始化cell
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        ModelCell *cell = [tableView dequeueReusableCellWithIdentifier:REUSE_MODEL_CELL];
        [cell accessModelAdapter:self.dataArray[indexPath.row]];
        
        return cell;
    }
    #pragma mark cell高度
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        ModelAdapter *adapter = self.dataArray[indexPath.row];
        return adapter.totalHeight;
    }
    @end

    简单的分析:

    1) 适配器与cell中的控件数据一一对应

    2) 重写适配器中的只读属性实现懒加载

    3) 适配器与cell共用一部分cell的控件属性,用以方便修改

    4) 适配器可以随时切换数据类型

    5) 用适配器处理业务逻辑

  • 相关阅读:
    继续致歉
    向大家致歉!!
    访问速度调查
    致歉
    [功能改进]通过Blog客户端直接发随笔至网站分类
    带宽升级公告
    创业团队的类型
    [讨论]基于.NET的开源论坛软件的选择
    调整一下工作的节奏
    公告
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4285075.html
Copyright © 2011-2022 走看看