用适配器模式处理复杂的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) 用适配器处理业务逻辑

 

目录
相关文章
|
6月前
|
开发者 iOS开发
介绍 UITableView 和 UICollectionView,它们的区别是什么?
介绍 UITableView 和 UICollectionView,它们的区别是什么?
170 0
|
iOS开发 开发者
iOS开发-简述UITableView中cell的重用问题
iOS开发-简述UITableView中cell的重用问题
189 0
UIView层次管理(sendSubviewToBack,bringSubviewToFront)
UIView层次管理(sendSubviewToBack,bringSubviewToFront)
550 0
|
容器
UIView与CALayer的关系
UIView与CALayer的关系
465 0
|
iOS开发 容器
(五)UITableView的用法一
(五)UITableView的用法一
195 0
|
存储 iOS开发 搜索推荐