一、纯代码自定义等高cell


首先创建一个继承UITableViewCell的类
@interface XMGTgCell : UITableViewCell
在该类中依次做一下操作
1.添加子控件

 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// 图片
UIImageView *iconImageView = [[UIImageView alloc] init];
[self.contentView addSubview:iconImageView];
self.iconImageView = iconImageView; // 标题
UILabel *titleLabel = [[UILabel alloc] init];
[self.contentView addSubview:titleLabel];
self.titleLabel = titleLabel; // 价格
UILabel *priceLabel = [[UILabel alloc] init];
[self.contentView addSubview:priceLabel];
self.priceLabel = priceLabel; // 购买数
UILabel *buyCountLabel = [[UILabel alloc] init];
[self.contentView addSubview:buyCountLabel];
self.buyCountLabel = buyCountLabel;
}
return self;
}

创建子控件

2.布局子控件

/**

* 需要注意的是通过initWithStyle:创建cell,就不会调用下面这个方法
* - (instancetype)initWithFrame:(CGRect)frame;
* 那么可以在layoutSubviews中计算所有子控件的frame

* 需求:图片与lable之间,lable与屏幕的margin都是10(加配图)
*/

 - (void)layoutSubviews
{
[super layoutSubviews]; CGFloat margin = ;
CGFloat contentH = self.contentView.frame.size.height;
CGFloat contentW = self.contentView.frame.size.width; // 图片
CGFloat iconX = margin;
CGFloat iconY = margin;
CGFloat iconW = ;
CGFloat iconH = contentH - * iconY;
self.iconImageView.frame = CGRectMake(iconX, iconY, iconW, iconH); // 标题
CGFloat titleX = iconX + iconW + margin;
CGFloat titleY = iconY;
CGFloat titleW = contentW - titleX - margin;
CGFloat titleH = ;
self.titleLabel.frame = CGRectMake(titleX, titleY, titleW, titleH); // 价格
CGFloat priceX = titleX;
CGFloat priceH = ;
CGFloat priceY = iconY + iconH - priceH;
CGFloat priceW = ;
self.priceLabel.frame = CGRectMake(priceX, priceY, priceW, priceH); // 购买数
CGFloat buyCountW = ;
CGFloat buyCountH = ;
CGFloat buyCountX = contentW - margin - buyCountW;
CGFloat buyCountY = iconY + iconH - buyCountH;
self.buyCountLabel.frame = CGRectMake(buyCountX, buyCountY, buyCountW, buyCountH);
}

布局子控件

3.设置子控件数据
在设置数据之前,我们可以创建一个TG类,用于保存每一个cell的数据,这就是典型的数据转模型,在前面也有介绍过,比如我们的数据是这样的

实现代码:

 /******************* XMGTg.h *******************/
#import <Foundation/Foundation.h> @interface XMGTg : NSObject
/** 标题 */
@property (nonatomic, copy) NSString *title;
/** 购买数 */
@property (nonatomic, copy) NSString *buyCount;
/** 图片 */
@property (nonatomic, copy) NSString *icon;
/** 价格 */
@property (nonatomic, copy) NSString *price; + (instancetype)tgWithDict:(NSDictionary *)dict;
@end /******************* XMGTg.m *******************/
#import "XMGTg.h" @implementation XMGTg
+ (instancetype)tgWithDict:(NSDictionary *)dict
{
XMGTg *tg = [[self alloc] init];
[tg setValuesForKeysWithDictionary:dict];
return tg;
}
@end /******************* XMGTgCell *******************/
#import <UIKit/UIKit.h>
@class XMGTg; @interface XMGTgCell : UITableViewCell
/** 团购模型数据 */
@property (nonatomic, strong) XMGTg *tg;
@end // 那么重写tg的setter方法就可以设置数据了
- (void)setTg:(XMGTg *)tg
{
_tg = tg; self.iconImageView.image = [UIImage imageNamed:tg.icon];
self.titleLabel.text = tg.title;
self.priceLabel.text = [NSString stringWithFormat:@"¥%@", tg.price];
self.buyCountLabel.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount];
}

设置子控件数据

二、Autolayout布局子控件(Masonry)


在布局控件时我们可以使用三方框架,Masonry
那么我么可以直接把创建子控件以及布局控件全部写在
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
这个方法中

 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
CGFloat margin = ; // 图片
UIImageView *iconImageView = [[UIImageView alloc] init];
[self.contentView addSubview:iconImageView];
self.iconImageView = iconImageView; [iconImageView makeConstraints:^(MASConstraintMaker *make) {
make.left.top.equalTo(self.contentView).offset(margin);
make.bottom.equalTo(self.contentView).offset(-margin);
make.width.equalTo();
}]; // 标题
UILabel *titleLabel = [[UILabel alloc] init];
[self.contentView addSubview:titleLabel];
self.titleLabel = titleLabel; [titleLabel makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(iconImageView);
make.left.equalTo(iconImageView.right).offset(margin);
make.height.equalTo();
make.right.equalTo(self.contentView).offset(-margin);
}]; // 价格
UILabel *priceLabel = [[UILabel alloc] init];
priceLabel.font = [UIFont systemFontOfSize:];
priceLabel.textColor = [UIColor orangeColor];
[self.contentView addSubview:priceLabel];
self.priceLabel = priceLabel; [priceLabel makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(titleLabel);
make.bottom.equalTo(iconImageView);
make.size.equalTo(CGSizeMake(, ));
}]; // 购买数
UILabel *buyCountLabel = [[UILabel alloc] init];
buyCountLabel.font = [UIFont systemFontOfSize:];
buyCountLabel.textColor = [UIColor grayColor];
buyCountLabel.textAlignment = NSTextAlignmentRight;
[self.contentView addSubview:buyCountLabel];
self.buyCountLabel = buyCountLabel; [buyCountLabel makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(iconImageView);
make.right.equalTo(titleLabel);
make.size.equalTo(CGSizeMake(, ));
}];
}
return self;
}

使用三方框架布局子控件

三、字典转模型的几种方式(MJExtension)


1.遍历数组
一般最笨的方法分以下三步:加载字典数组、创建模型数组、将字典数组转换为模型数组
示例代码如下:

 - (NSArray *)tgs
{
if (!_tgs) {
// 加载字典数组
NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tgs" ofType:@"plist"]]; // 创建模型数组
NSMutableArray *tgArray = [NSMutableArray array]; // 将字典数组 -> 模型数组
for (NSDictionary *dict in dictArray) {
XMGTg *tg = [XMGTg tgWithDict:dict];
[tgArray addObject:tg];
}
_tgs = tgArray;
}
return _tgs;
}

2.世界流行框架MJExtension
再来看看用李明杰的MJExtension框架怎么解决
有一个方法,一句话可以解决

_tgs = [XMGTg objectArrayWithFilename:@"tgs.plist"];

或者这样

_tgs = [XMGTg objectArrayWithFile:[[NSBundle mainBundle] pathForResource:@"tgs" ofType:@"plist"]];

或是这样

_tgs = [XMGTg objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tgs" ofType:@"plist"]]];

那么在上次说到的索引条案例中可以这样写

// 懒加载
- (NSArray *)cargroups
{
if (!_cargroups) {
// 提前告诉CarGroup类其中的Cars数组要解析成什么模型数组
[CarGroup setupObjectClassInArray:^NSDictionary *{
return @{
@"cars": @"Car"
};
}];
_cargroups = [CarGroup objectArrayWithFilename:@"cars.plist"]; }
return _cargroups;
}

四、xib自定义等高的cell


首先可以先创建一个名为XMGTgCell继承UITableViewCell的类
然后创建你想要的xib文件


并且xib中的Custom Class中的class一定要设置成XMGTgCell
最后在XMGTgCell的实现中重写

- (void)setTg:(XMGTg *)tg
设置数据

 #import <UIKit/UIKit.h>

 @class XMGTg;

 @interface XMGTgCell : UITableViewCell
/** 团购模型数据 */
@property (nonatomic, strong) XMGTg *tg;
@end #import "XMGTgCell.h"
#import "XMGTg.h" @interface XMGTgCell()
@property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UILabel *priceLabel;
@property (weak, nonatomic) IBOutlet UILabel *buyCountLabel;
@end @implementation XMGTgCell - (void)setTg:(XMGTg *)tg
{
_tg = tg; self.iconImageView.image = [UIImage imageNamed:tg.icon];
self.titleLabel.text = tg.title;
self.priceLabel.text = [NSString stringWithFormat:@"¥%@", tg.price];
self.buyCountLabel.text = [NSString stringWithFormat:@"%@人已购买", tg.buyCount];
}
@end

五、不同类型的cell共存


首先在cellForRowAtIndexPath方法中返回不同类型的cell

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row % == ) {
XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:tgID];
cell.tg = self.tgs[indexPath.row];
return cell;
} else {
XMGNewsCell *cell = [tableView dequeueReusableCellWithIdentifier:newsID];
return cell;
}
}

并且在使用这些cell之前要先注册

- (void)viewDidLoad {
[super viewDidLoad]; self.tableView.rowHeight = ; [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGTgCell class]) bundle:nil] forCellReuseIdentifier:tgID];
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGNewsCell class]) bundle:nil] forCellReuseIdentifier:newsID];
}

效果如下

六、storyboard自定义cell


这两种不同的cell绑定的Identifier分别为:tg、test
那么让我们来看下代码

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row % == ) {
static NSString *ID = @"tg";
XMGTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; cell.tg = self.tgs[indexPath.row]; return cell;
} else {
return [tableView dequeueReusableCellWithIdentifier:@"test"];
}
}

如果我们在viewDidLoad注册一个Identifier为tg,并且类型为UITableViewCell的cell,会出现什么情况呢

- (void)viewDidLoad {
[super viewDidLoad]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"tg"];
}

经过测试,发现运行程序会直接蹦了,并且报了一个错误
reason: '-[UITableViewCell setTg:]: unrecognized selector sent to instance 0x7f8fcbc2be70'

这里是什么意思呢,首先在这里要知道 "当缓存池中找不到cell 的时候,先根据重用标识从注册这里找,然后再从storysboard中找"
这个错误的意思是发送了一个不能识别的消息-[UITableViewCell setTg:]
也就是说UITableViewCell中的setTg方法它找不到,程序运行到
"cell.tg = self.tgs[indexPath.row];这一句时就会报错,因为我们根本没有在UITableViewCell里创建tg这个属性,自然也就找不到tg的set方法,进而可以验证上面所说的系统会优先选择代码创建的cell而不是storyboard里的"

七、分割线,静态cell


分割线的原理:实际上cell中的Content View的高度要比cell少1左右的高度(大概),那么我们可以紧贴着Content View底部添加一个高度为0~1、宽度等于cell的view,并把颜色设置为灰色,最好将self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;不显示分割线

静态cell,iPhone的设置界面就是用的静态cell

八、团购案例(TG)

最后是今天自己敲的完整的代码

团购案例

 #import <UIKit/UIKit.h>

 @interface ViewController : UITableViewController

 @end

 #import "ViewController.h"
#import "TgCellTableViewCell.h"
#import "MJExtension.h"
#import "TgCell.h" #define ID @"chgCell" @interface ViewController ()
@property (nonatomic, strong) NSArray *tgCells;
@end @implementation ViewController
- (NSArray *)tgCells
{
if (nil == _tgCells) {
_tgCells = [TgCell objectArrayWithFilename:@"tgs.plist"];
}
return _tgCells;
} - (void)viewDidLoad {
[super viewDidLoad];
self.tableView.rowHeight = ; // self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerClass:[TgCellTableViewCell class] forCellReuseIdentifier:ID]; } - (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.tgCells.count;
} - (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
TgCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
cell.tgcell = self.tgCells[indexPath.row]; return cell;
}
@end /**************** TgCellTableViewCell*******************/
#import <UIKit/UIKit.h>
#import "TgCell.h"
@interface TgCellTableViewCell : UITableViewCell
@property (nonatomic, strong) TgCell *tgcell;
@end #import "TgCellTableViewCell.h" @interface TgCellTableViewCell()
// 图标
@property (nonatomic, weak) UIImageView *icon_imageView;
// 标题
@property (nonatomic, weak) UILabel *titel_lable;
// 价格
@property (nonatomic, weak) UILabel *price_lable;
// 购买人数
@property (nonatomic, weak) UILabel *buy_lable; @end @implementation TgCellTableViewCell // 添加一个灰色的边框
- (void)awakeFromNib
{
self.layer.borderWidth = ;
self.layer.borderColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:0.3].CGColor;
} // 添加所有子控件
- (nonnull instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// 1.创建图标
UIImageView *icon_imageView = [[UIImageView alloc] init];
[self.contentView addSubview:icon_imageView];
self.icon_imageView = icon_imageView; // 2.创建标题
UILabel *titel_lable = [[UILabel alloc] init];
[self.contentView addSubview:titel_lable];
self.titel_lable = titel_lable; // 3.创建价格
UILabel *price_lable = [[UILabel alloc] init];
[self.contentView addSubview:price_lable];
price_lable.textColor = [UIColor orangeColor];
price_lable.font = [UIFont systemFontOfSize:];
self.price_lable = price_lable; // 4.创建购买人数
UILabel *buy_lable = [[UILabel alloc] init];
[self.contentView addSubview:buy_lable];
buy_lable.textAlignment = NSTextAlignmentRight;
buy_lable.textColor = [UIColor grayColor];
buy_lable.font = [UIFont systemFontOfSize:];
self.buy_lable = buy_lable; }
return self;
} // 布局控件
- (void)layoutSubviews
{
[super layoutSubviews]; CGFloat margin = ;
CGFloat contentW = self.contentView.frame.size.width;
CGFloat contentH = self.contentView.frame.size.height;
// 设置frame
// 1、设置图标的frame
CGFloat icon_imageViewX = margin;
CGFloat icon_imageViewY = margin;
CGFloat icon_imageViewW = ;
CGFloat icon_imageViewH = contentH - * margin;
self.icon_imageView.frame = CGRectMake(icon_imageViewX, icon_imageViewY, icon_imageViewW, icon_imageViewH); // 2、设置标题的frame
CGFloat titel_lableX = CGRectGetMaxX(self.icon_imageView.frame) + margin;
CGFloat titel_lableY = margin;
CGFloat titel_lableW = contentW - titel_lableX - margin;
CGFloat titel_lableH = ;
self.titel_lable.frame = CGRectMake(titel_lableX, titel_lableY, titel_lableW, titel_lableH); // 3、设置价格的frame
CGFloat price_lableX = titel_lableX;
CGFloat price_lableH = ;
CGFloat price_lableW = ;
CGFloat price_lableY = CGRectGetMaxY(self.icon_imageView.frame) - price_lableH;
self.price_lable.frame = CGRectMake(price_lableX, price_lableY, price_lableW, price_lableH); // 4、设置购买人数的frame
CGFloat buy_lableX = CGRectGetMaxX(self.price_lable.frame) + margin;
CGFloat buy_lableH = ;
CGFloat buy_lableY = CGRectGetMaxY(self.icon_imageView.frame) - buy_lableH;
CGFloat buy_lableW = contentW - buy_lableX - margin;
self.buy_lable.frame = CGRectMake(buy_lableX, buy_lableY, buy_lableW, buy_lableH); } - (void)setTgcell:(TgCell *)tgcell
{
_tgcell = tgcell; self.icon_imageView.image = [UIImage imageNamed:tgcell.icon];
self.titel_lable.text = tgcell.title;
self.price_lable.text = [NSString stringWithFormat:@"¥%@",tgcell.price];
self.buy_lable.text = [NSString stringWithFormat:@"%@人购买",tgcell.buyCount];
} @end /**************** TgCell*******************/
#import <Foundation/Foundation.h> @interface TgCell : NSObject
/** 标题 */
@property (nonatomic, copy) NSString *title;
/** 购买数 */
@property (nonatomic, copy) NSString *buyCount;
/** 图片 */
@property (nonatomic, copy) NSString *icon;
/** 价格 */
@property (nonatomic, copy) NSString *price;
@end #import "TgCell.h" @implementation TgCell @end

iOS开发——UI进阶篇(二)自定义等高cell,xib自定义等高的cell,Autolayout布局子控件,团购案例的更多相关文章

  1. iOS开发——UI进阶篇(三)自定义不等高cell,如何拿到cell的行高,自动计算cell高度,(有配图,无配图)微博案例

    一.纯代码自定义不等高cell 废话不多说,直接来看下面这个例子先来看下微博的最终效果 首先创建一个继承UITableViewController的控制器@interface ViewControll ...

  2. iOS开发——UI进阶篇(十)导航控制器、微博详情页、控制器的View的生命周期

    一.导航控制器出栈 1.initWithRootViewController本质 UIViewController *vc = [[OneViewController alloc] init]; // ...

  3. iOS开发——UI进阶篇(十二)事件处理,触摸事件,UITouch,UIEvent,响应者链条,手势识别

    触摸事件 在用户使用app过程中,会产生各种各样的事件 一.iOS中的事件可以分为3大类型 触摸事件加速计事件远程控制事件 响应者对象在iOS中不是任何对象都能处理事件,只有继承了UIResponde ...

  4. iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果

    一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // re ...

  5. iOS开发——UI进阶篇(四)tableView的全局刷新,局部刷新,左滑操作,左滑出现更多按钮,进入编辑模式,批量删除,自定义批量删除

    首先创建项目,在storyboard如下布局控件,设置好约束 然后创建cell模型类XMGWineCell数据模型类XMGWine创建UITableView,设置数据源协议,实现数据源方法懒加载数据这 ...

  6. iOS开发——UI进阶篇(十五)Quartz2D介绍

    一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘 ...

  7. iOS开发——UI进阶篇(七)程序启动原理、打电话、发短信

    一.Info.plist常见的设置 1.建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 ...

  8. iOS开发——UI进阶篇(十七)CALayer,核心动画基本使用

    一.CALayer简介 1.CALayer在iOS中,文本输入框.一个图标等等,这些都是UIView你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个其实UIView之所以 ...

  9. iOS开发——UI进阶篇(十六)Quartz2D实战小例子

    一.画线 只有在drawRect中才能获取到跟view相关联的上下文 - (void)drawRect:(CGRect)rect {} 一条线 // 1.获取跟当前View相关联的layer上下文(画 ...

随机推荐

  1. Git连接到自己的GitHub仓库

    1.配置本地git $git config --global user.name "xxx" $git config --global user.email "xxxxx ...

  2. BZOJ3685: 普通van Emde Boas树

    显然这题的所有操作都可以用set,但是直接用set肯定要T,考虑到读入量较大,使用fread读入优化,就可以卡过去了. #include<bits/stdc++.h> using name ...

  3. 多级反向代理下,Java获取请求客户端的真实IP地址多中方法整合

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  4. WinForm------如何跳转另一个窗口,同时关闭当前窗口

    添加一个按钮,并为按钮添加点击事件(注:Frm_Main为需要跳转的窗口名字) private void Btn_OK_Click(object sender, EventArgs e) { //打开 ...

  5. 记一次DDos攻击--2016/12/8

    先上图 图一 图二 午休之后~ 睡意朦胧,报警来了.看到121121Mbps的流量攻击,精神一震. 不到两秒,又来了一个短信,开始心塞.网站入口IP被封了.打开网站,全站瘫痪.紧接着运营就来了,让运营 ...

  6. js实现观察者模式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 单个pdf提取测试

    # -*- coding: utf-8 -*- """ Created on Wed Feb 3 09:32:22 2016 pdf单个文件提取测试 @author: A ...

  8. Windows 无法自动将 IP 协议堆栈绑定到网络适配器。解

    Windows 无法自动将 IP 协议堆栈绑定到网络适配器.解  昨天断网了,所以把珍藏已久的无线网卡拿出来蹭网.我系统是Windows 7 但是装上去东显示已启用,就是用不了,用windows诊断是 ...

  9. 单点登录(SSO)系统的总结

    前些天一位其他开发部门的同事找到我们了解一些关于SSO单点登录的事,他们要做单点登录,同时也需要和我们这边的系统做集成,要我帮忙做一单点登录,了解关于单点登录的解决方案和资料,虽然做单点登录已经很久了 ...

  10. Shader

    Shader的学习方法总结 http://www.cnblogs.com/Esfog/p/How_To_Learn_Shader.html [Shader 着色器]学习shader之前必须知道的东西之 ...