用适配器模式处理复杂的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) 用适配器处理业务逻辑
用适配器模式处理复杂的UITableView中cell的业务逻辑
原文:http://www.cnblogs.com/YouXianMing/p/4285075.html