你的位置:首页 > 操作系统

[操作系统]cell高度自动适应文章内容


效果:

描述:表视图中生成多个不同的cell,cell的高度跟文字内容的多少有关

一 : 创建工程文件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)dealloc11 {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 : UITableViewController4 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   // 根据下标取出相对应的cell123   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中的值赋值给summaryLabel102   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 code135 }136 137 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {138   [super setSelected:selected animated:animated];139 140   // Configure the view for the selected state141 }142 143 @end