首先向大家致歉,自从上一篇使用 UITableView 创建表格应用演练(3)——使用区段分类显示表格数据博文发布后,因工作原因始终未能抽出时间更新博客。
今天给大家介绍一下如何在表格应用中使用自定义单元格以及选中单元格的一个简单操作。
本文目标
本文以上一篇为基础,对应用进行扩展,介绍以下内容:
- 在表格应用中自定义单元格布局显示;
- 选中某一单元格,并在Safari中打开用户链接地址;
一. 自定义单元格演练
首先我们回顾一下前文,在演练(2)中,我们定义数据结构时,定义了一个名为:Favorite的属性,用于表示我们对该微博账户的喜好程度。本节演练中,我们就通过自定义单元格的方式,在表格中以五角星的形式显示喜好程度,本节演练结束后,您将看到以下运行结果:
开始之前,我们需要准备几张星星的图片,请猛击此处MyFocusDemo4Images.zip下载。
准备就绪,让我们开始吧:D
1. 打开My Focus工程;
2. 将下载并解压缩后的三个图片文件拖拽到“Images”组下并放手,弹出下图对话框:
确认勾选了“Copy items into destination groups' folder(if needed)”复选框后,点击“Finish”按钮;
3. 在导航区域点击并打开“MainStoryboard.storyboard”文件,在左侧“Table View Controller Scene”中展开并选中“Table View Cell - userInfoCell”,此时的界面如下图所示:
4. 在右侧工具区域的“Objects”列表中选择一个ImageView控件拖放到表格单元左侧,然后我们再选择一个Label控件,拖放到刚刚那个ImageView的右侧,然后再依次拖放五个ImageView控件,顺序摆放在Label控件的右侧。在此,我们可以用鼠标调整一下各个控件的大小和位置,使得界面看起来更加美观一些。我们甚至还可以调整一下Label控件的文本颜色。如下图所示:
5. 此时,按Command+R运行一下程序,怎么和上次演练之后的运行结果一样呢?没有发生任何变化啊。
对,因为我们还没有告诉应用怎么和我们刚才调整过的界面结合再一起,下面我们就来做这个工作。
6. 在导航区域的“GUI”群组文件夹上,点击鼠标右键,选择“New File...”在弹出的对话框中选择“Objective-C class”,然后点击“Next”按钮;
7. 在弹出的“Choose options for your new file”对话框中,在“Class”文本框位置输入:JOYUserInfoCell,在“Subclass of”下拉框中,选择或者直接输入“UITableViewCell”,然后点击“Next”按钮,如下图所示:
8. 在弹出的对话框中,直接点击“Create”按钮,创建文件并关闭对话框;
9. 在导航区域点击并打开新建的“JOYUserInfoCell.h”文件,输入属性定义代码,输入完成后,如下所示:
1 #import <UIKit/UIKit.h> 2 3 @interface JOYUserInfoCell : UITableViewCell 4 5 @property (strong, nonatomic) IBOutlet UIImageView *userImage; 6 @property (strong, nonatomic) IBOutlet UILabel *userNameLabel; 7 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage1; 8 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage2; 9 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage3; 10 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage4; 11 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage5; 12 13 @end
10. 在导航区域点击并打开新建的“JOYUserInfoCell.m”文件,@implementation语句后输入一些@synthesize属性定义语句,如下所示:
1 @implementation JOYUserInfoCell 2 // 1. 属性合成定义 3 @synthesize userImage = _userImage; 4 @synthesize userNameLabel = _userNameLabel; 5 @synthesize favoriteImage1 = _favoriteImage1; 6 @synthesize favoriteImage2 = _favoriteImage2; 7 @synthesize favoriteImage3 = _favoriteImage3; 8 @synthesize favoriteImage4 = _favoriteImage4; 9 @synthesize favoriteImage5 = _favoriteImage5;
说明:所谓属性合成定义,是对getter、setter的一种简化表现形式。这样,我们可以避免写很多很多的,说实话,大量的getter、setter是一个很痛苦的事情。当然,在Objective-c中,您也可以自己来写getter和setter,稍后演练中会有所涉及。
11. 在导航区域,再次点击并打开“MainStoryboard”文件,下面我们来看看如何将界面的UI控件和类属性成员进行绑定:D。
12. 在左侧“Table View Controller Scene”面板中,选中“User Info Cell - userInfoCell”,然后在右侧工具区域顶部,选择“Show the Identity inspector”,然后在下方的“Custom Class”区域的“Class”下拉列表中,将原有的“UITableViewCell”修改为我们刚刚定义的“JOYUserInfoCell”,如下图所示:
13. 在左侧“Table View Controller Scene”面板中,确认点击并选中“User Info Cell - userInfoCell”(有时候焦点可能会丢失,再点一下就好了),然后在右侧工具区域顶部,选择“Show the Connections inspector”,如下图所示:
看到什么了?对!就是我们刚才在 JOYUserInfoCell.h 中定义的那些 IBOutlet 属性。
说明:IB是Interface Builder的缩写,如果您希望定义的属性在Interface Builder中可见,则在属性定义时加上 IBOutlet 关键字即可。
14. 在右侧面板的Outlets区域中,将鼠标指针移动到“userImage”右侧的空心圆点上时,该圆点会变成一个灰色的加号,点击并按住鼠标,然后拖放到左侧面板的第一个“Image View”上放手,拖拽过程中会有一条灰色的线条出现。这样我们第一个连接就建立好了,如下图所示:
15. 下面我们依次建立其他控件与自定义类的连接关系,建立完成之后的效果,如下图所示:
说明:建立连接的过程中,需要注意控件与属性的关系是否一一对应,在右侧“Outlets”面板中,上下移动鼠标,随着指针的移动,中心区域的控件会根据鼠标所在位置高亮显示。如果发现错了,您可以点击右侧面板中的小叉子,删除连接关系,然后重复上述操作,重新建立连接。
啰嗦了半天,写了很多的字,实际上等熟练,之后,你会发现这个操作是非常的简单和省时的,也是一件非常快乐的事情。
16. 开始下一步之前,我们先做一个操作,因为这个操作马上就要用到。还记得我们在演练(1)建立UITableViewController的时候,曾经设定过表格单元的“Identifier”吗?如下图所示:
可是这个设定貌似一直没有用过,不要着急,不要着急,马上就要用到了:D
17. 按Command+R再次运行程序,怎么还是和上次演练之后的运行结果一样呢?忙乎了这么久,为什么一点变化也没有呢?
因为我们还没有告诉程序如何识别表格单元。下面我们来看看如何做吧。
18. 在导航区域点击并打开我们久违的“JOYTableViewController.m”文件,找到- (UITableViewCell *)tableView方法,我们先看一下前几句代码:
1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 2 { 3 static NSString *CellIdentifier = @"Cell"; 4 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 5 6 // Configure the cell...
这是在创建对象时,系统默认生成的代码。看到了吗?
对,就是这里出了问题!下面我们将方法中的代码进行简单的调整,调整之前,我们先在文件头部加上一句:
1 #import "JOYUserInfoCell.h"
否则编译器不知道去哪里找 JOYUserInfoCell 这个类,调整后的代码如下所示:
1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 2 { 3 // 1. 修改单元格标示 4 static NSString *CellIdentifier = @"userInfoCell"; 5 // 2. 修改单元格属性,使其继承自 JOYFocusUserCell 6 JOYUserInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 7 8 // Configure the cell... 9 // 实例化单元格对象 10 if (cell == nil) { 11 // 3. 修改示例化对象属性 12 cell = [[JOYUserInfoCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 13 } 14 15 JOYCategory *category = [_categoryList objectAtIndex:[indexPath section]]; 16 JOYFocusUser *user = [category.userList objectAtIndex:[indexPath row]]; 17 18 // 4. 设置单元格属性 19 [cell.userNameLabel setText:user.userName]; 20 [cell.userImage setImage:user.image]; 21 22 return cell; 23 }
下面我们来做根据不同用户的Favorite数值,在用户名称的左侧显示五角星。
19. 在导航区域,点击并打开“JOYUserInfoCell.h”文件,在 IBOutlet 属性下方,添加一个属性,代码如下:
1 #import <UIKit/UIKit.h> 2 3 @interface JOYUserInfoCell : UITableViewCell 4 5 @property (strong, nonatomic) IBOutlet UIImageView *userImage; 6 @property (strong, nonatomic) IBOutlet UILabel *userNameLabel; 7 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage1; 8 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage2; 9 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage3; 10 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage4; 11 @property (strong, nonatomic) IBOutlet UIImageView *favoriteImage5; 12 13 @property (assign, nonatomic) CGFloat favorite; 14 15 @end
20. 按 Control + Command + 下箭头直接打开“JOYUserInfoCell.m”文件,添加部分代码,具体调整见以下代码中的注释。
1 #import "JOYUserInfoCell.h" 2 3 // 1. 接口定义 4 @interface JOYUserInfoCell() { 5 // 2. 私有成员变量 6 @private 7 CGFloat _favorite; // 喜好程度数值 8 9 UIImage *_fullStarImage; // 完整星星图像 10 UIImage *_halfStarImage; // 半颗星星图像 11 UIImage *_emptyStarImage; // 空白星星图像 12 } 13 14 @end 15 16 @implementation JOYUserInfoCell 17 @synthesize userImage = _userImage; 18 @synthesize userNameLabel = _userNameLabel; 19 @synthesize favoriteImage1 = _favoriteImage1; 20 @synthesize favoriteImage2 = _favoriteImage2; 21 @synthesize favoriteImage3 = _favoriteImage3; 22 @synthesize favoriteImage4 = _favoriteImage4; 23 @synthesize favoriteImage5 = _favoriteImage5; 24 25 // 3. 26 #pragma mark - getter & setter 27 // 设置喜好数值 28 - (void)setFavorite:(CGFloat)favorite { 29 _favorite = favorite; 30 } 31 32 // 返回喜好数值 33 - (CGFloat)favorite { 34 return _favorite; 35 } 36 37 // 4. 添加程序运行时对象初始化方法 38 - (id)initWithCoder:(NSCoder *)aDecoder { 39 self = [super initWithCoder:aDecoder]; 40 41 if (self) { 42 _fullStarImage = [UIImage imageNamed:@"star_full.png"]; 43 _halfStarImage = [UIImage imageNamed:@"star_half.png"]; 44 _emptyStarImage = [UIImage imageNamed:@"star_empty.png"]; 45 } 46 return self; 47 } 48 49 //- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 50 //{ 51 // self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 52 // if (self) { 53 // // Initialization code 54 // } 55 // return self; 56 //} 57 58 - (void)setSelected:(BOOL)selected animated:(BOOL)animated 59 { 60 [super setSelected:selected animated:animated]; 61 62 // Configure the view for the selected state 63 } 64 65 @end
21. 下面我们来对setFavorite的实现做一些简单的处理,代码如下:
1 // 设置喜好数值 2 - (void)setFavorite:(CGFloat)favorite { 3 // A. 数值范围校验 4 if ((favorite > 5.0f) || (favorite < 0.0f)) { 5 favorite = 0.0f; 6 } 7 8 // B. 定义数值便于循环处理 9 [self.favoriteImage1 setImage:_emptyStarImage]; 10 NSArray *favoriteImages = [[NSArray alloc]initWithObjects:_favoriteImage5, 11 _favoriteImage4, 12 _favoriteImage3, 13 _favoriteImage2, 14 _favoriteImage1, 15 nil]; 16 17 // C. 依次判断每个UIImageView应该显示的图像内容 18 NSInteger x = favorite * 10; 19 for (NSInteger i = 5; i > 0; i--) { 20 UIImageView *image = [favoriteImages objectAtIndex:(5 - i)]; 21 22 if ((x / 10) >= i) { 23 [image setImage:_fullStarImage]; 24 } else if (((x % 10) > 0) && ((x / 10) == (i - 1))) { 25 [image setImage:_halfStarImage]; 26 } else { 27 [image setImage:_emptyStarImage]; 28 } 29 } 30 31 _favorite = favorite; 32 }
22. 在导航区域点击并打开“JOYTableViewController.m”文件,找到- (UITableViewCell *)tableView方法,在设置头像语句后面添加一句:
1 cell.favorite = user.favorite;
23. 按Command+R再次运行程序,激动人心的时刻到了!!!如下图所示:
怎么样,效果还不错吧,而且不复杂吧:D,本节内容貌似写了不少,其实大部分时间都是在用鼠标拖来拖去,真正写代码的时间还是很少的。
二. 选中某一单元格并在Safari中打开用户链接地址
1. 在导航区域,点击并打开“JOYUserInfoCell.h”文件,在 IBOutlet 属性下方,添加一个属性,代码如下:
1 @property (strong, nonatomic) NSString *webSite;
2. 按 Control + Command + 下箭头直接打开“JOYUserInfoCell.m”文件,在
@implementation JOYUserInfoCell
语句下,添加 @synthesize 属性定义,代码如下:
1 @synthesize webSite = _webSite;
3. 修改文件末尾的setSelected方法,代码如下:
1 - (void)setSelected:(BOOL)selected animated:(BOOL)animated 2 { 3 [super setSelected:selected animated:animated]; 4 5 // Configure the view for the selected state 6 if (selected) { 7 NSURL *url = [NSURL URLWithString:_webSite]; 8 9 if (![[UIApplication sharedApplication]openURL:url]){ 10 NSLog(@"%@%@",@"Failed to open url:",[url description]); 11 } 12 } 13 }
4. 在导航区域点击并打开“JOYTableViewController.m”文件,找到- (UITableViewCell *)tableView方法,在设置头像语句后面添加一句:
cell.webSite = user.webSite;
5. 按Command+R再次运行程序,然后点击某一个单元格试试看运行效果。:D
三. 小结
至此,表格应用演练算是基本告一段落了。原本还打算在本演练中写一些有关Navigation控件的使用以及数据编辑存储相关内容的。
但是考虑到类似文章网上已经有不少了,另外本人前段时间工作原因导致这个演练系列拖得有点久,再次表示歉意。
本演练源程序下载地址:JoyiOSMyFocus4.zip
近期计划写一些有关Objective-C语法相关的演练教程,敬请关注。