http://www.haohtml.com/program/ios/201301/47828.html原文
启动Xcode,创建一个新的项目“Single View application(单一视图的应用程序)”。
Xcode项目模板选择
点击“Next(下一步)”继续。再次,填写所需的所有选项的Xcode项目:
· Product Name(产品名称):SimpleTable-这是您的应用程序的名称。
· Company Identifier(公司标识):com.appcoda -它实际上是域名反写。如果你有一个域,您可以使用您自己的域名。否则,你可能会使用我们的,或者只需填写在“edu.self”。
· Class Prefix(类前缀):SimpleTable - Xcode使用的类的前缀自动命名类。以后,你可以选择自己的前缀,甚至留空白。但在本教程中,让我们保持简单,使用“SimpleTable”好了。
· Device Family(设备系列):iPhone -使用“iPhone”这个项目。
· Use Storyboards(使用故事板): [unchecked] -不要选择此选项。这个简单的项目我们不需要故事板。
· Use Automatic Reference Counting(使用自动的引用计数):[checked]-默认情况下,这应该被启用。不用管他。
· Include Unit Tests(包括单元测试):[unchecked] -不要选中此复选框。现在,你不需要单元测试类。
SimpleTable项目选项
点击“Next(下一步)”继续。Xcode然后问你在哪里保存 “SimpleTable”的项目。选择任何文件夹(例如桌面)来您的项目。并且,取消Source Control(源代码管理)选项。单击“Create(创建)”继续。
选择一个文件夹来保存你的项目
当你确认,Xcode根据您所提供的选项自动创建“SimpleTable的”项目。结果屏幕看起来像这样:
主屏的SimpleTable项目的
首先,我们将创建用户界面和添加表视图。选择“SimpleTableViewController.xib”切换到界面生成器。
Interface Builder中SimpleTable项目
在对象库中,选择“Table View(表视图)”对象,并将其拖动到视图中。
插入“表视图”后您的屏幕应该像下面这样。
在继续之前,请尝试使用模拟器来运行你的应用程序。单击“Run(运行)”按钮来建立你的应用程序并测试它。
模拟器的屏幕上会看起来像这样:
很简单,对不对?你已经在你的应用程序添加表视图了。但就目前而言,它不包含任何数据。接下来,我们将编写一些代码,来添加数据到表中。
回到Project Navigator(项目导航器)中,选择“SimpleTableViewController.h”。 “UIViewController”后添加“<UITableViewDelegate, UITableViewDataSource>”。你的代码应该象下面这样:
1
|
#import <UIKit/UIKit.h>
|
在Objective-C ,“UITableViewDelegate”和“UITableViewDataSource”被称为协议。基本上,为了在表视图中显示数据,我们必须遵循协议规定的要求,并实现所有强制性方法。
此前,我们已经在头文件中添加了“UITableViewDelegate”和“UITableViewDataSource”协议,。这可能会有点混乱。他们是干什么的呢?
在表视图后的实际类UITableView,,被设计成灵活处理各种不同类型的数据。您可能会显示一个列表的国家或联系人的姓名。或者像这个例子,我们将使用表视图呈现食谱列表。那么,你如何告诉UITableView的列表中要显示的数据呢?UITableViewDataSource就是答案。这是您的数据和表视图之间的链接。UITableViewDataSource协议声明了两个你必须实现的方法(tableView:cellForRowAtIndexPath and tableView:numberOfRowsInSection),。通过实施这些方法,你告诉表视图中显示多少行,和每行中的数据。
另一方面,UITableViewDelegate,涉及到UITableView的外观。协议的可选方法,让你管理表里单个行的高度,配置表头和表尾,重新排序表格单元格。在这个例子中我们不改写这些方法。让我们把他们留在未来的教程把。
接着,选择“SimpleTableViewController.m”,并定义一个实例变量的表中的数据。
1
|
@implementation SimpleTableViewController
|
在方法view DidLoad中,添加以下代码,来初始化”tableData“数组。我们用食谱列表来初始化数组。
1
|
- (void)viewDidLoad
|
数组是一种计算机编程里的基本数据结构。你可以把一个数组作为数据元素的集合。回到上述代码中的数组tableData在,它代表文本元素的集合。您可以把数组想像成这样:
数组元素中的每一个都能被识别或通过索引来访问。具有10个元素的数组,将具有从0到9的目录。这意味着,tableData [0]返回的“tableData”数组的第一个元素。
在Objective C,NSArray是用于创建和管理数组的类。您可以使用NSArray创建大小固定的静态数组。如果你需要一个动态数组,可以使用NSMutableArray。
NSArray提供工厂方法来创建一个数组对象。在我们的代码中,我们使用“arrayWithObjects”来实例化一个NSArray对象,并预载特定元素(如汉堡包)。
您还可以使用内置的方法来查询和管理数组。之后,我们将调用“count”的方法来查询数组中的数据元素数量。要了解更多有关NSArray的使用方法,你可以经常参考苹果的官方文件。
最后,我们必须添加两个数据源方法:“tableView:numberOfRowsInSection”和“tableView:cellForRowAtIndexPath”。这两种方法都是UITableViewDataSource协议的一部分。配置一个UITableView时,这是必须实现的方法。第一种方法是告知一个表视图页面中有多少行。因此,让我们添加下面的代码。“count”的方法只是简单返回在“tableData”数组的项目数。
1
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
下一步,我们实现所需的其他方法。
1
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
每次显示时表行,“cellForRowAtIndexPath”方法被执行。下面的插图会给你一个更好地了解关于UITableView、UITableDataSource如何工作。
UITableView和UITableDataSource如何一起工作
好吧,让我们点击“Run(运行)”按钮,并试验您的最终应用程序!如果你正确地编写代码,在模拟器运行的程序是这样的:
为什么它仍然是空白呢?我们已经写好生成表中数据、实现了所需方法的代码。但是,为什么表视图没有像预期那样显示呢?
其实一件事情。
像 第一个教程中“Hello World”按钮,我们要建立表视图和我们刚刚创建的两个方法之间的连接。
返回到“SimpleTableViewController.xib”。按住键盘上的Control键,选择表视图并拖动到“File’s Owner(文件的所有者)”。您的屏幕应该是这样的:
连接表视图的数据源和委托
松开按钮,将显示“数据源”和“委托”弹出式窗口。选择“数据源”,建立表视图和数据源之间的连接。重复上述步骤,并与委托进行连接。
连接数据源和委托
就是这样。为了确保是否连接正确,您可以选择表视图。在Utility area(实用区域)的上半部分,您可以在“Connection Inspector”(即最右边的标签页)显示现有连接。
显示连接检查
最后,它已经准备好测试您的应用程序。只要按一下“运行”按钮,让您的模拟器加载应用程序:
表视图是过于平淡,是吧?给每一行添加添加图像怎么样?iOS的SDK使得它非常容易就做到这一点。你只需要为插入每一行的缩略图添加一行代码。
首先,下载这个示例图像。或者,您可以使用自己的图像,但要确保你的图片名字是“creme_brulee.jpg”。在项目浏览器中,用鼠标右键单击的“SimplyTable”文件夹,选择“Add Files to SimpleTable…”。
图像添加到您的项目
选择图像文件,并选中“Copy items to destination group(将项目复制到目标组的文件夹)”复选框。单击“确定”添加文件。
选择你的图像文件,并添加到项目中
现在,编辑“SimpleTableViewController.m”,并添加下面这行代码到“tableView:cellForRowAtIndexPath”方法:
1
|
cell.imageView.image = [UIImage imageNamed:@"creme_brelee.jpg"];
|
编辑后,你的代码应该是这样的:
选择你的图像文件,并添加到项目中
这行代码的用处是加载图像并显示在表格单元格的图像区域中。现在,再次点击“Run(运行)”按钮,您的SimpleTable应用程序应在每一行显示图像:
在我们更改代码之前,让我们回顾显示缩略图的代码。
最后,我们增加了一个行代码指示UITableView每一行显示“creme_brelee.jpg”这张图片。显然,为了显示不同的图像,我们需要改变这行代码。正如之前解释的那样,IOS在显示一条表单元格时自动调用“cellForRowAtIndexPath”方法
1
|
-
(UITableViewCell
*
)tableView
:
(UITableView
*
)tableView cellForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
|
看看该方法的参数,每次调用时通过“indexPath”来传递表单元格信息。indexPath参数包含的表单元格的行数(以及节号)。您可以简单地使用“indexPath.row”属性,找出当前指向哪一行。和数组一样,表行的计数从零开始。换言之,对于第一行“indexPath.row”返回0。
因此,为了显示不同的缩略图,我们将添加一个新的数组(即缩略图),存储文件名的缩略图:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@implementation SimpleTableViewController
{ NSArray *tableData; NSArray *thumbnails; } - ( void )viewDidLoad { [super viewDidLoad ]; // Initialize table data tableData = [ NSArray arrayWithObjects : @ "Egg Benedict", @ "Mushroom Risotto", @ "Full Breakfast", @ "Hamburger", @ "Ham and Egg Sandwich", @ "Creme Brelee", @ "White Chocolate Donut", @ "Starbucks Coffee", @ "Vegetable Curry", @ "Instant Noodle with Egg", @ "Noodle with BBQ Pork", @ "Japanese Noodle with Pork", @ "Green Tea", @ "Thai Shrimp Cake", @ "Angry Birds Cake", @ "Ham and Cheese Panini", nil ]; // Initialize thumbnails thumbnails = [ NSArray arrayWithObjects : @ "egg_benedict.jpg", @ "mushroom_risotto.jpg", @ "full_breakfast.jpg", @ "hamburger.jpg", @ "ham_and_egg_sandwich.jpg", @ "creme_brelee.jpg", @ "white_chocolate_donut.jpg", @ "starbucks_coffee.jpg", @ "vegetable_curry.jpg", @ "instant_noodle_with_egg.jpg", @ "noodle_with_bbq_pork.jpg", @ "japanese_noodle_with_pork.jpg", @ "green_tea.jpg", @ "thai_shrimp_cake.jpg", @ "angry_birds_cake.jpg", @ "ham_and_cheese_panini.jpg", nil ]; } |
正如你可以从上面的代码中看到的,我们用图像文件名列表初始化了的缩略图数组。图像的顺序排列与“tableData”对齐。
为了您的方便,您可以下载该图像包,并把它们添加到您的项目,确保“Copy items into destination group’s folder”已勾选当然你也可以用自己的图片。
添加的图像文件后,你应该会在Project Navigator中发现他们,如下面的屏幕:
最后,更改在cellForRowAtIndexPath“方法的代码:
1
|
cell.imageView.image
=
[
UIImage的imageNamed
:
[
缩略图objectAtIndex
:
indexPath.row
]
]
;
|
这行代码获取特定行的图像名字。就是说,indexPath.row属性对于第一行返回0,我们使用“objectAtIndex”的方法选取图像数组的第一个(即egg_benedict.jpg)。
保存所有的更改后,再次尝试运行您的应用程序。现在应该不同的表中单元格显示缩略图:
应用程序是否可以更好看?我们将通过自定义表格单元格使其更好看。到目前为止,我们使用的默认样式显示表单元格,而且缩略图的位置和大小是固定的。如果你想就像下面的屏幕显示的那样使缩略图更大并附上每个菜的准备时间,怎么办?
不同风格的自定义表格视图单元格
在这种情况下,你必须创建和设计自己的表格单元格。返回到Xcode。在项目浏览器中,右键单击“SimpleTable”文件夹并选择“New File ...”。
为了设计我们自己的表格单元格,我们要创建一个新的表格单元格界面生成器。在这种情况下,我们只需要启动一个“空”的用户界面。点击“下一步”继续。
选择一个空的Interface Builder文档
当提示选择设备系列时,选择“iPhone”,然后单击“下一步”继续。保存的文件为“SimpleTableCell”。
一旦该文件被创建时,你就能在Project Navigator中找到它。选择“SimpleTableCell.xib”切换到界面生成器。我们要设计的自定义表格单元格的外观。
在对象库中,选择“Table View Cell(表格视图单元格)”,将其拖动到界面生成器的设计区域。
为了容纳更大的缩略图,我们要改变单元格的高度。只要按住下/上侧的单元格边缘并缩放到高度78。
或者,您也可以使用“Size Inspector”改变高度。
表查看单元格的尺寸督察
下一步,选择“Attributes Inspector(属性检查器)“的上半部分的通用区域来为自定义单元格“SimpleTableCell”设置“Identifier(标识符)”。这个标识符将在后面的代码中使用。
表格单元格视图配置好之后,我们将往他里面放其他元素。选择“Image View”,并把它拖到表视图单元格。
image view用于显示缩略图。您可以调整其大小,使其适合单元格。参考数值,我设置的高度和宽度为69像素。
接下来,我们将添加三个标签:Name(姓名),Prep Time(准备时间)和Time(时间)。“Name”标签将用于显示配方的名称。“Prep Time”是一个静态的标签,只显示“准备时间”。最后,“Time”的标签是一个动态的标签被用于显示实际的具体菜肴的准备时间。
要添加一个标签,在Object library(对象库)中选择“标签”,将其拖动到单元格中。您可以双击标签以更改其名称。
和上面所显示的做比较,您可能会发现您的字体大小和样式是不同的。要更改字体样式,只需选择标签并选择“Attribute Inspector(属性检查器)”。从这里,你可以改变“字体”和最小字体大小的设置。您也可以通过检查更改文本颜色和对齐方式。
您的最终设计应该类似于这样:
到目前为止,我们已经设计了表格单元格。但如何才能改变自定义单元格的标签值吗?我们要为自定义表视图单元格创建一个新的类。这个类代表了自定义单元格的底层数据模型。
就像以前一样,右键单击“SimpleTable的项目浏览器”文件夹中,然后选择“新建文件”。
选择一个新的文件模板
选择该选项后,Xcode会提示你选择一个模板。我们要创建一个新的自定义表格视图单元格类,选择“Objective-C类”下的“Cocoa Touch”,然后单击“下一步”。
为您的项目创建新的文件
类名填写“SimpleTableCell”,选中"Subclass of "里的“UITableViewCell”。
单击“下一步”,保存的文件在SimpleTable项目文件夹,并单击“创建”继续。Xcode将在Project Navigator中创建两个名为“SimpleTableCell.h”文件和“SimpleTableCell.m”。
正如前面提到的中,SimpleTableCell类作为自定义单元格的数据模型。在单元格中,我们有三个值是可变的:thumbnail image view(缩略图图像视图),name label(名称标签)和time label(时间标签)。在这个类里,我们将添加三个属性来表示这些动态值。
打开“SimpleTableCell.h”和之前的“@end”行中添加以下属性:
1
2 3 |
@property
(nonatomic, weak
) IBOutlet UILabel
*nameLabel;
@property (nonatomic, weak ) IBOutlet UILabel *prepTimeLabel; @property (nonatomic, weak ) IBOutlet UIImageView *thumbnailImageView; |
@property (attributes) type name;
参考上面的代码,weak和nonatomic是attributes。UILabel和UIImageView是type,而“nameLabel”,“prepTimeLabel”和“thumbnailImageView”是name。
那么,IBOutlet是什么?你可以把IBOutlet想成一个指令。为了与表视图单元格(即SimpleTableCell.xib)中的元素相关联,我们使用关键字“IBOutlet”让Interface Builder中知道,他们被允许连接。后来,你会看到如何使这些outlets和在Interface Builder中的对象之间的连接。
现在,打开“SimpleTableCell.m”,以下“@implementation SimpleTableCell”下面添加以下代码:
1
2 3 |
@synthesize nameLabel
= _nameLabel;
@synthesize prepTimeLabel = _prepTimeLabel; @synthesize thumbnailImageView = _thumbnailImageView; |
“@synthesize”关键字告诉编译器自动生成代码来访问我们前面声明的属性。如果你忘了这个指令,Xcode会象下面这样报错:
保存更改并选择“SimpleTableCell.xib”回到Interface Builder中。现在我们可以在类的属性和Label/ ImageView之间创建连接。
首先,选择单元格,在“Identity Inspector”中把类改为“SimpleTableCell”,这样就可以在单元格视图和我们之前创建的类之间建立联系。
现在,我们要建立的连接的属性。右键单击"Objects"下的“SimpleTableCell”,以显示“Outlets”查询器。单击并按住“nameLabel”旁边的圆圈,并将其拖动到Label – Name”对象。Xcode会自动建立连接。
为“prepTimeLabel”和“thumbnailImageView”重复上述操作:
View”:
当你建立所有的连接后,它看起来应该是这样的:
我们已经完成了自定义表格单元格的设计和编码。最后,我们来到最后修改的部分 - 确认自定义单元格放在SimpleTableViewController中。
让我们重温在“SimpleTableView.m”的代码:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-
(UITableViewCell
*
)tableView
:
(UITableView
*
)tableView cellForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
{ static NSString *simpleTableIdentifier = @ "SimpleTableItem"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier :simpleTableIdentifier ]; if (cell == nil ) { cell = [ [UITableViewCell alloc ] initWithStyle :UITableViewCellStyleDefault reuseIdentifier :simpleTableIdentifier ]; } cell.textLabel.text = [tableData objectAtIndex :indexPath.row ]; cell.imageView.image = [UIImage imageNamed : [thumbnails objectAtIndex :indexPath.row ] ]; return cell; } |
我们先前使用默认的表视图单元格(即UITableViewCell)显示的表项。为了使用我们的自定义表格单元格,我们必须改变在“SimpleTableView.m”代码:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-
(UITableViewCell
*
)tableView
:
(UITableView
*
)tableView cellForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
{ static NSString *simpleTableIdentifier = @ "SimpleTableCell"; SimpleTableCell *cell = (SimpleTableCell * ) [tableView dequeueReusableCellWithIdentifier :simpleTableIdentifier ]; if (cell == nil ) { NSArray *nib = [ [ NSBundle mainBundle ] loadNibNamed : @ "SimpleTableCell" owner :self options : nil ]; cell = [nib objectAtIndex : 0 ]; } cell.nameLabel.text = [tableData objectAtIndex :indexPath.row ]; cell.thumbnailImageView.image = [UIImage imageNamed : [thumbnails objectAtIndex :indexPath.row ] ]; cell.prepTimeLabel.text = [prepTime objectAtIndex :indexPath.row ]; return cell; } |
然而,当你你更新代码后,,Xcode检测会有一些错误在源代码编辑器。
源代码的错误指示由Xcode
有什么问题吗?我们刚刚修改的代码告诉“SimpleTableViewController”去使用“SimpleTableCell”类的表格单元格。然而,“SimpleTableViewController”不知道“SimpleTableCell”类。这就是为什么Xcode会显示错误。
正如在第一个教程说的,一个头文件中声明一个类的接口。对于“SimpleTableViewController”要认识“SimpleTableCell”,我们必须在“SimpleTableViewController.m”导入“SimpleTableCell.h”。
导入SimpleTableCell.h
通过导入“SimpleTableCell.h”,“SimpleTableViewController”知道"SimpleTableCell是什么并可以利用它。
最后,由于表格单元格的高度改为78,在“@end”前面添加下面的代码。
1
2 3 4 |
-
(CGFloat
)tableView
:
(UITableView
*
)tableView heightForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
{ return 78; } |
现在,点击“Run”按钮和您的SimpleTable的应用程序看起来应该象下面这样: