效果:
描述:表视图中生成多个不同的cell,cell的高度跟文字内容的多少有关
要求:需要自己在网上下载一个plis文件,然后修改两个标题
一 : 创建工程文件UIAutomaticCellHeightPractce-11
二 : 这里使用手动释放,所以需要修改工程文件Automatic Reference Counting 修改为NO
三 : 修改引用计数方式
四 : 释放适量变量,以及对父集进行释放,并让自动释放self.window(autorelease)
五 : 导入.plist文件(直接拖进工程文件)
六 : 工程文件
七 :代码区(采用MVC的设计模式)
模型-视图-控制器(Model-View-Controller,MVC)
AppDelegate.h
1 #import <UIKit/UIKit.h>
2
3 @interface AppDelegate : UIResponder <UIApplicationDelegate>
4
5 @property (retain, nonatomic) UIWindow *window;
6
7
8 @end
AppDelegate.m
1 #import "AppDelegate.h"
2 #import "RootTableViewController.h"
3
4 @interface AppDelegate ()
5
6 @end
7
8 @implementation AppDelegate
9
10 - (void)dealloc
11 {
12 self.window = nil;
13
14 [super dealloc];
15 }
16
17 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
18 self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
19 // Override point for customization after application launch.
20 RootTableViewController *rootVC = [[RootTableViewController alloc] init];
21
22 UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootVC];
23
24 self.window.rootViewController = navigationController;
25
26 [rootVC release];
27
28 [navigationController release];
29
30
31 self.window.backgroundColor = [UIColor whiteColor];
32 [self.window makeKeyAndVisible];
33 return YES;
34 }
35
36 @end
RootTableViewController.h
1 #import <UIKit/UIKit.h>
2
3 @interface RootTableViewController : UITableViewController
4
5 @end
RootTableViewController.m
1 #import "RootTableViewController.h"
2 #import "CellViewModel.h"
3 #import "CellTableViewCell.h"
4 #define kCellTabelViewCell @"cell"
5
6 @interface RootTableViewController ()
7
8 // 创建公用数组
9 @property (nonatomic , retain) NSMutableArray *dataSourceArr;
10
11 @end
12
13 @implementation RootTableViewController
14
15 - (void)dealloc
16 {
17 self.dataSourceArr = nil;
18
19 [super dealloc];
20 }
21
22 - (void)viewDidLoad {
23 [super viewDidLoad];
24
25 [self readDataFromNewsData];
26
27 // 注册CellTableView
28 [self.tableView registerClass:[CellTableViewCell class] forCellReuseIdentifier:kCellTabelViewCell];
29
30 // Uncomment the following line to preserve selection between presentations.
31 // self.clearsSelectionOnViewWillAppear = NO;
32
33 // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
34 // self.navigationItem.rightBarButtonItem = self.editButtonItem;
35 }
36
37 #pragma mark - 给dataSourceArr添加懒加载方法
38 -(NSMutableArray *)dataSourceArr {
39
40 if (!_dataSourceArr) {
41
42 self.dataSourceArr = [NSMutableArray arrayWithCapacity:0];
43 }
44
45 return [[_dataSourceArr retain] autorelease];
46 }
47
48
49 #pragma mark - 读取数据
50 -(void)readDataFromNewsData {
51
52 // NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:0];
53
54 // 创建文件路径
55 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"NewsData.plist" ofType:nil];
56
57 // 根据路径将文件中的内容取出来存储到字典中
58 NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
59
60 // 根据key值取出对应的value值,这里假设要查找的文件内容为title,summary
61 NSArray *arr = dic[@"news"];
62
63 // NSLog(@"%@" , arr);
64
65 for (NSDictionary *d in arr) {
66
67 // 创建一个CellViewModel对象存储数据
68 CellViewModel *dataBase = [[CellViewModel alloc] init];
69
70 // 使用kvc的方法给CellViewModel对象赋值
71
72 /*
73 2)代码说明:
74
75 KVC key valued coding 键值编码
76
77 1)使用KVC间接修改对象属性时,系统会自动判断对象属性的类型,并完成转换。如该程序中的“23”.
78
79 2)KVC按照键值路径取值时,如果对象不包含指定的键值,会自动进入对象内部,查找对象属性
80 */
81
82 [dataBase setValuesForKeysWithDictionary:d];
83
84 // NSLog(@"%@" , dataBase);
85
86 // 将存储到CellViewModel对象的数据放入数组
87 [self.dataSourceArr addObject:dataBase];
88
89 // NSLog(@"%@" , _dataSourceArr);
90
91 // 释放
92 [dataBase release];
93 }
94 }
95
96
97 - (void)didReceiveMemoryWarning {
98 [super didReceiveMemoryWarning];
99 // Dispose of any resources that can be recreated.
100 }
101
102 #pragma mark - Table view data source (表视图数据源)
103
104 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
105 //#warning Potentially incomplete method implementation.
106 // Return the number of sections.
107
108 // 创建一个分区
109 return 1;
110 }
111
112 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
113 //#warning Incomplete method implementation.
114 // Return the number of rows in the section.
115
116 // 分区中成员个数
117 return self.dataSourceArr.count;
118 }
119
120 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
121
122 // 根据下标取出相对应的cell
123 CellViewModel *cellModel = self.dataSourceArr[indexPath.row];
124
125 return [CellTableViewCell cellHeight:cellModel];
126 }
127
128 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
129
130 // 使用据有identifier标示的方法,在重用池中取值
131 CellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellTabelViewCell forIndexPath:indexPath];
132
133 // 根据数组下标取出对应的CellViewModel类型的数据
134 CellViewModel *cellModel = self.dataSourceArr[indexPath.row];
135
136 // 将CellViewModel对象中的值传入CellTableViewCell类型对象
137 [cell passValue:cellModel];
138
139 return cell;
140 }
141
142 @end
CellViewModel.h
1 #import <Foundation/Foundation.h>
2 #import <UIKit/UIKit.h> // Foundationg框架下无法使用UIKit框架下的内容,在这里引入UIKit框架; 注意引入系统文件使用<>
3
4 @interface CellViewModel : NSObject
5
6 // 创建控件,这里空间名称要与要取出的数据的key相同,这样使用kvc赋值的时候才能成功
7 @property (nonatomic , copy) NSString *title;
8
9 @property (nonatomic , copy) NSString *summary;
10
11 @end
CellViewModel.m
1 #import "CellViewModel.h"
2
3 @implementation CellViewModel
4
5 - (void)dealloc
6 {
7 self.title = nil;
8
9 self.summary = nil;
10
11 [super dealloc];
12 }
13
14 // 防止未找到对应的key值而crash,需要写一下下面的对象
15 -(void)setValue:(id)value forUndefinedKey:(NSString *)key {
16
17 // 里面可以什么都不写
18 // NSLog(@"%@ -- %@" , key , value);
19 }
20 @end
CellTableViewCell.h
1 #import <UIKit/UIKit.h>
2 @class CellViewModel;
3
4 @interface CellTableViewCell : UITableViewCell
5
6 #pragma mark - 创建一个类返回cell的高度
7 + (CGFloat)cellHeight:(CellViewModel *)cellViewModel;
8
9 #pragma mark - 创建一个接口,让外部可以通过这个接口传值
10 -(void)passValue:(CellViewModel *)cellViewModel;
11
12 @end
CellTableViewCell.m
1 #import "CellTableViewCell.h" 2 #import "CellViewModel.h" 3 4 @interface CellTableViewCell () 5 6 // 创建标题Label视图 7 @property (nonatomic , retain) UILabel *titleLabel; 8 9 // 创建摘要Label视图 10 @property (nonatomic , retain) UILabel *summaryLabel; 11 12 @end 13 14 @implementation CellTableViewCell 15 16 17 - (void)dealloc 18 { 19 self.titleLabel = nil; 20 21 self.summaryLabel = nil; 22 23 [super dealloc]; 24 } 25 26 27 #pragma mark - 创建属性的懒加载方式 28 // 懒加载方式的创建步骤 29 // 1. 必须有属性 30 // 2. 重写属性的getter方法,如果为空那么就创建, 如果有就直接使用 31 // 好处: 1. 真正使用的时候采取创建它,有效的降低了内存 2. 通过懒加载能够有效的分隔代码块 32 33 -(UILabel *)titleLabel { 34 35 if (!_titleLabel) { 36 37 self.titleLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 300, 30)] autorelease]; 38 39 // 此处最好不要使用self.的方法,因为self.属于getter方法,getter方法中不能套用getter方法,不然就会无限调用 40 // 设置背景色用于观察控件位置 41 // _titleLabel.backgroundColor = [UIColor redColor]; 42 } 43 // 安全释放 44 return [[_titleLabel retain] autorelease]; 45 } 46 47 -(UILabel *)summaryLabel { 48 49 if (!_summaryLabel) { 50 self.summaryLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 50, 300, 30)] autorelease]; 51 52 _summaryLabel.numberOfLines = 0; // 行数设置为0,指的就是文字内容自动适应宽度(自动换行); 53 54 // 设置背景色用于观察控件位置 55 // _summaryLabel.backgroundColor = [UIColor redColor]; 56 57 // 设置label文字大小 58 _summaryLabel.font = [UIFont systemFontOfSize:15.0]; 59 } 60 61 // 安全释放 62 return [[_summaryLabel retain] autorelease]; 63 } 64 65 66 #pragma mark - 创建一个类返回summary文字内容的总高度 67 + (CGFloat)summaryHeight:(CellViewModel *)cellViewModel { 68 69 // CGRect rect = [cellViewModel.summary boundingRectWithSize:<#(CGSize)#> options:<#(NSStringDrawingOptions)#> attributes:<#(NSDictionary *)#> context:<#(NSStringDrawingContext *)#>] 70 // 71 // return rect.size.height; 72 // 上面方法可以返回文字的宽度高度: 需要提供一个CGSize, NSStringDrawingOptions, NSDictionary对象 73 // 1. 绘制文本大小,这里要和summary一样宽,但是到不不用管 74 CGSize contentSize = CGSizeMake(300, 0); // 这里只需提供宽度就可以了 75 76 // 2. 设置文本绘制标准(使用系统提供) 77 78 // 3. 设置文字属性(注意: 文字的大小要和summaryLabel设置的保持一致) 79 NSDictionary *dic = @{NSFontAttributeName : [UIFont boldSystemFontOfSize:15.0]}; 80 81 // 返回文本rect 82 CGRect rect = [cellViewModel.summary boundingRectWithSize:contentSize options:(NSStringDrawingUsesLineFragmentOrigin) attributes:dic context:nil]; 83 84 return rect.size.height; 85 } 86 87 88 #pragma mark - 创建一个类返回cell的高度 89 + (CGFloat)cellHeight:(CellViewModel *)cellViewModel { 90 91 // self在类方法中使用,代表的就是类, 在对象方法中代表的就是对象 92 return 10 + 30 + 10 + [self summaryHeight:cellViewModel]; 93 } 94 95 #pragma mark - 创建一个接口,让外部可以通过这个接口传值 96 -(void)passValue:(CellViewModel *)cellViewModel { 97 98 // 将model中的值赋值给titleLabel 99 self.titleLabel.text = cellViewModel.title; 100 101 // 将model中的值赋值给summaryLabel 102 self.summaryLabel.text = cellViewModel.summary; 103 104 // 让_summary的高度变化适应文字内容 105 // _summaryLabel.frame = CGRectMake(10, 50, [[self class] summaryHeight:cellViewModel], 300); 106 107 // 在对象方法中由于self代表的是对象,所以要进行一下转换 108 // [self class] 返回一个类 109 CGFloat height = [[self class] summaryHeight:cellViewModel]; 110 111 CGRect sFrame = self.summaryLabel.frame; 112 113 sFrame.size.height = height; 114 115 self.summaryLabel.frame = sFrame; 116 } 117 118 119 #pragma mark - 重写初始化将titleLabel和summaryLabel添加到表视图的contentView上 120 -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 121 122 // 判断父类是否初始化 123 if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 124 125 [self.contentView addSubview:self.titleLabel]; // 这里必须使用self.的方式调用属性,不能使用_的方式 126 127 [self.contentView addSubview:self.summaryLabel]; 128 } 129 130 return self; 131 } 132 133 - (void)awakeFromNib { 134 // Initialization code 135 } 136 137 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 138 [super setSelected:selected animated:animated]; 139 140 // Configure the view for the selected state 141 } 142 143 @end