在iOS7中使用storyboardpart1 及prototypecell使用 storyboard cell 重用

Storyboard是一项令人兴奋的功能,在iOS5中首次推出,在开发app的界面时可以极大地节省时间。
在iOS7中使用storyboard(part1)及prototypecell使用 storyboard cell 重用
如下图所示,这就是一个完整的应用的storyboard,接下来我们要学习如何通过这种方式创建应用。现在你可能还不是很精确地知道我们的应用可以做什么,但是通过上图,我们可以很清晰的明白这些视图之间的关系。这就是使用storyboard的强大之处。当你的应用有许多不同页面的时候,通过使用storyboard,可以大大减少页面之间跳转的代码。过去我们为每个视图控制器创建一个nib文件,现在,只需要使用一个storyboard,它包含了你应用中所有的视图控制器以及它们之间的关系。相比传统的nib文件,storyboard有很多优点:1.使用storyboard,可以更好地理解应用中所有视图在概念上的概览以及它们之间的关系。掌控所有的视图变得很容易,因为所有的设计都是在一个文件中,而不是在很多单独的nib文件中。2.storyboard描述了视图之间的动画,这些动画叫做"segues"你可以很容易的通过从一个视图控制器(点ctrl-dragging)拖拽到另一个来实现,感谢"segues"让我们不需要写代码去控制页面跳转了。3.storyboard通过新的cell原型,以及静态cell的特性,让表格控制器实现起来更容易了。你近乎可以完全的通过storyboard来设计你的表格控制器,这也大大的减少了你不得不写的代码量。.并不是所有的都是那么完美,当然使用storyboard也是有一些限制的,storyboard的Interface builder远没有旧版nib编辑器那么强大,并且有一些东西只能在nib中做而不能在storyboard编辑器中做。还有,你需要一个大号的显示器,尤其是在开发iPad应用的时候。如果你是那种不喜欢用Interface builder画界面而是用代码直接写界面的人,很遗憾,storyboard并不适合你。就个人而言,我比较倾向于写的代码越少越好,特别是控制UI的那种,所以storyboard简直就是为我准备的一把利器。当然了,如果你想继续使用nib,那么继续用好了,你需要知道的是你可以通过storyboard来绑定各视图控制器,对于使用storyboard,还是旧版的nib,不是一个非做选择不可的事,随你好了。在这个例子中,我们将会学到--通过storyboard我们可以做什么,我们将会创建一个简单的应用,功能大致是有一个现实玩家,游戏,以及玩家技能评分的这么一个列表。在学习过程中,你几乎可以学到大多数通过故事板可以做到的事。storyboard教程 : iOS 7版打开Xcode创建一个新项目,这里我们用 SingleView Application 模板:按照下面的方式填写模板中的选项:1.Product Name:Ratings2.Organization Name:随便写点什么都行3.CompanyIdentifier:域名反过来写,例如com.xx.xx4.Class Prefix: 空着就行5.Devices: iPhone用旧版Xcode的时候你需要特别指定下这个新项目是用storyboard的,但XCode5之后,不再有这个选项了,默认就是用storyboard创建的项目。在Xcode创建完项目之后,Xcode的主界面上应该如下图所示:这个新项目包含2个类:AppDelegate和ViewController,以及我们这个例子中的明星:Main.storyboard文件.请注意,这个项目中并没有xib文件。这是一个只支持竖屏的应用,所以在继续之前,钩掉DeploymentInfo, Device Orientation下面的 Landscape Left和Landscape Right选项。接下来让我们看一下storyboard,点击列表中的Main.storyboard 在interface builder中打开它。在Interfacebuilder中编辑storyboard就跟编辑nib文件差不多,你可以从ObjectLibrary中拖拽新的元素到视图控制器中,并且可以编辑它的布局。区别在于storyboard不仅仅有一个视图控制器,它把你应用中的所有视图控制器全都包含了。按标准的storyboard的说法,一个视图控制器就是一个"场景"。你可以交替的使用这个模式,"场景"是呈现在storyboard中的视图控制器,以往,你可能为每一个"场景"/视图控制器创建一个nib文件。现在你只需要把他们都集中在一个storyboard里。在iPhone中,一次只能看到一个场景,而iPad应用中,一次可能会看到多个。例如"master/detail"或者 "popover"注意:Xcode5默认storyboard以及nib中的 Auto Layout属性是打开的。 Auto Layout是一个新的很帅气的可以自动调整控件大小的这么一个技术,在应用适配iPad以及iPhone5的时候尤其有用,可惜它只能在 iOS 6以上运行。当然了,它也需要一定的学习曲线,这个例子中我们不会详细的说这点。如果你有兴趣了解 Auto Layout,请参阅我们的书籍《iOS 6 by Tutorials andiOS 7 by Tutorials》.在storyboard中的File inspector禁用Auto Layout选项,如下图:拖拽一些控件到空的视图控制器上,感受一些storyboard编辑器是如何工作的。在storyboard编辑页面中找到下面这个标上红色左箭头的按钮点击它打开左侧的 Document Outline视图当编辑nib的时候,列表中显示的是这个nib中所有的控件,但对于storyboard,它会显示你的应用中的所有视图控制器的内容。上图只有一个视图控制器,在接下来的例子中,我们会增加其他的。在scene下面有微型版的DocumentOutline,叫做Dock, 如下图:什么是 Dock?它显示了当前视图的最上层对象,每个视图都至少有一个View Controller 对象,一个First Responder对象,一个Exit 项目。当然了,它也可能会有其他的最上层对象。使用Dock 去连接outlets 和actions变的非常容易,当你想把某个对象连接到视图控制器中时,只需简单地把它的图标拖拽到Dock上。注意: 你很可能没怎么用过FirstResponder。这是指任何物体在任何给定时间具有第一响应状态的代理对象。它一直在你的nib中,你很可能从来没有必要使用它。举个例子,按钮中有个TouchUp Inside事件,把它拖给First Responder的 cut:selector。如果在某一点的文本字段具有输入焦点,那么你可以按下该按钮,使文字栏位,也就是现在的第一响应者,切其文本到剪贴板。运行该app,它看起来应该和你在编辑器中设计的一样(此处使用了运行iOS 7的4-inch Retina iPhonesimulator):如果你写过以nib为基础的应用,通常会有一个叫做MainWindow.xib的文件。这个文件有一个UIWindow对象指向AppDelegate,以及其他视图控制器。当你想用storyboard做这些的时候,就不需要MainWindow.xib了。那么storyboard是如何加载到应用中的呢?让我们看看应用的 applicationdelegate。 打开 AppDelegate.h,看起来应该是这样:
  1. #import
  2. @interfaceAppDelegate:UIResponder
  3. @property(strong,nonatomic)UIWindow*window;
  4. @end
使用storyboard,应用代理必须继承自UIResponder,并且有一个 UIWindows属性。下面打开AppDelegate.m,这里设么都没有,所有的方法都是空的,甚至application:didFinishLaunchingWithOptions:也仅仅是返回了一个YES。秘密藏在Ratings-Info.plist里,让我们在SupportingFiles group 里找到并打开它,如下图:storyboard使用UIMainStoryboardFile或者"Mainstoryboard file base name"来指定当应用启动的时候,哪一个storyboard是必须被加载的。当设置生效,UIApplication会自动加载叫这个被命名的storyboard文件,并把它第一个视图控制器显示到UIWindow中。这些都不必写代码去实现。这些你还可以通过修改ProjectSettings下面的ProjectSettings来实现,如下图:出于完整性, 打开 main.m 如下图:
  1. #import
  2. #import"AppDelegate.h"
  3. intmain(intargc,char*argv[])
  4. {
  5. @autoreleasepool{
  6. returnUIApplicationMain(argc,argv,nil,NSStringFromClass([AppDelegateclass]));
  7. }
  8. }
app delegate并不是storyboard的一部分,我们需要把它的名字指定给UIApplicationMain()否则,应用就会找不到它。把它加到标签上这个Ratings 应用是由标签控制的2个视图,使用storyboard,创建标签很容易。回到Main.storyboard, 把一个Tab BarController 从Object Library 拖到面板中。你可能需要最大化你的XCode,因为Tab BarController 默认会带 2个视图控制器,你需要能完整的看到他们,通过右下角的小浮动窗口,可以缩小这个面板。一个新的Tab Bar Controller默认会带2个视图管理器,一个标签一个。UITabBarController也被叫做容器视图控制器,因为一般它都会包含一个以上的视图控制器。此外还有其他两种容器控制器:NavigationController和the Split View Controller。容器控制器通过箭头管理它的视图,如下图注意:如果你想把TabBar Controller的所有视图一起移动,你需要点?-click选中这些视图,然后再移动他们(被选中的视图会有一个蓝色的下划线)。在第一个视图控制器中拖入一个label并且设置它的text 为 "First Tab",同理,在第二个视图管理器中加入"SecondTab" 这可以让你看到标签切换后会发生什么情况。注意:在编辑器缩小的时候你不能向面板中拖入控件,你要先恢复到正常缩放水平,双击当前面板就可以做到。选中Tab Bar Controller看下面板中的Attributesinspector。选中那一栏指的是Initial ViewController。如下图:在画布上,先由一个箭头指向Tab barcontroller这意味着启动app时,UIApplication会把Tabbarcontroller作为主控制器。storyboard同伴有一个独立的视图控制器,他是特定的" initial view controller",它是storyboard的切入点。提示:改变initial view controller ,你可以通过拖拽在视图控制器之间的箭头。运行应用试试吧,现在应用的效果是有一个tab bar并且可以通过tab 去切换视图。如下图:Xcode可以创建一个以tab为模板的项目(Tabbed Application template) ,你以前应该用过,最好理解下它是如何工作的,如果非手动创建,也不至于手足无措。注意:当你想Tabbarcontroller中加入超过5个视图的时候,它会自动的生产一个 More的tab。删除模板自带的那个视图控制器,现在storyboard中只有一个tab bar 以及两个tab各自对应的一个视图。添加一个Table ViewController两个scene隶属的Tab BarController都是标准的 UIViewControllers,下面我们用UITableViewController 替换掉第一个tab 中的scene。点击并选中第一个视图控制器,然后删除它,从ObjectLibrary中拖拽一个新的Table ViewController到先前被删除的scene所处的位置。如下图:当Table ViewController选中时,在Xcode菜单栏选择EditorEmbed InNavigationController,现在另一个视图控制器被加到画板中了:你还需要从ObjectLibrary中拖一个Navigation Controller,但这种嵌入在命令行中一样简单。因为Navigation Controller也是一个容器视图控制器(跟Tab Bar Controller一样), 它有一个关系箭头指向Table ViewController,你还可以在 Document Outline看到这个关系:注意:嵌入Table ViewController给了它一个navigation bar,Interface Builder自动加上它的,因为当前视图会显示在NavigationController的frame里。它并不是一个真的UINavigationBar ,只是一个模拟的。打开Table ViewController的Attributes inspector, 你会看到上方有Simulated Metrics 选项,如下图:"Inferred"作为storyboards的默认值,它意味着视图将会显示一个navigation bar,当它处于NavigationController中时,显示一个tab bar 当它处于Tab BarController中时。你可以修改这些默认设置,但是注意,这里只是方便你设计用的,"SimulatedMetrics"并不会在运行时出现,他们是指一个虚拟的设计,用来展示你的视图最终会是什么样子。把这两个视图连接到Tab BarController,按Ctrl-drag 从 the Tab Bar Controller 到 the NavigationController如下图:松手的时候, 出现一个弹出窗口如下图:选择 Relationship Segue -view controllers,它为2个视图创建了一个关系箭头如下图:Tab Bar Controller有2个关系,给每个tab都有一个。Navigation Controller自己有一个关系指向Table ViewController。还有另一种类型的箭头"segue" 稍后我们会讲到它。创建完这个新的连接后,一个新的tab 添加到 TabBar Controller了, 简单的命名为"Item"。对于这个应用,你希望这个新视图作为第一个tab,所以拖动tabs,改变他们的顺序如下图:运行应用,第一个tab显示了一个包含在navagationcontroller 下面的 table view,如下图:在你为应用添加具体的功能之前,让我们先整理下storyboard,分别把第一个tab 第二个tab 命名为"Players" 和"Gestures"。并不像你期望的那样,你不能在Tab BarController 上改动,只可以在tab 指向的那个视图控制器上做。一旦你把一个视图控制器连上了Tab BarController,它默认会给一个 Tab Bar Item 对象。用这个Tab Bar Item去改变tab的名字跟图片。选中NavigationController里的Tab Bar Item ,在Attributes inspector中把title 设置为Players,如下图:同理把第二个tab 设置为Gestures.一个设计良好的应用需要在tab 上有图标。这里例子代码中 有个Images 的文件夹在 resource 文件夹下 把这个文件夹加入到项目中 ,选中Players TabBar的 Item的 Attributes inspector ,把 Players.png 填进去. 同理处理 Gesturesitem the 图片为 Gestures.png.一个嵌入在Navigation Controller的视图控制器有一个 Navigation Item,它是用来配制navigationbar的。在Table View Controller 中选中Navigation Item (在DocumentOutline可以找到)在 Attributes inspector 中把title改成Players.此外, 你可以双击navigation bar直接修改title. (注意: 你需要双击table view controller 中的simulated navigationbar,并不是Navigation Controller 中的真正的那个Navigation Bar 对象),如下图运行应用,看看这令人惊叹的tabbar吧,这一切,一行代码都不用写喔~PrototypecellsPrototype cells允许你在storyboard编辑器中直接为table view 设计自定义cell。默认Table View Controller会带一个空的cell. 点击它,设置 Attributes inspector 中的 Style 为 Subtitle.这会让你的cell 包含2个 labels.如果你以前为table view做过自定义cell,你可能注意到,这就是UITableViewCellStyleSubtitle风格。通过prototype cells你可以像刚刚那样直接选择自带的cell 风格,或者纯粹自己做一个设计。设置 Accessory attribute为DisclosureIndicator在 Identifier 中输入 PlayerCell. 所有的prototype cells 仍然是 UITableViewCell 类型 所以它们需要一个reuseidentifier,如下图:运行应用…什么都没变?这并没有什么值得奇怪的,你还需要为 这个tableview 指定一个datasource,这样它才会知道显示什么。添加一个新文件,选择Objective-Cclass模板,命名为PlayersViewContro ller,并且确保它是UITableViewController的子类。不要选中WithXIB for user interface 选项,因为你已经在storyboard中设计好它了,如下图:回到storyboard选择Table ViewController (确保你只选择了 tableviewcontroller 并没有其他的view 包含在内)。在 Identityinspector中设置它的 Class 为 PlayersViewController.这对于在storyboard中使用你自己定义的 视图控制器的类很重要,因为如果你不这么做,你的类永远都不会被使用!如下图:到目前为止当你运行应用的时候,你的tableviewcontroller 是从storyboard中加载的你的PlayersViewController的实例。添加一个mutable arrayproperty到PlayersViewController.h:
  1. #import
  2. @interfacePlayersViewController:UITableViewController
  3. @property(nonatomic,strong)NSMutableArray*players;
  4. @end
该数组将会包含你的应用中的主要数据模型,一个数组包含Player 对象。使用Objective-C class模板在项目中添加一个新文件,命名为Player, 继承自NSObject.把Player.h改成下图的样子:
  1. @interfacePlayer:NSObject
  2. @property(nonatomic,copy)NSString*name;
  3. @property(nonatomic,copy)NSString*game;
  4. @property(nonatomic,assign)intrating;
  5. @end
这并没有什么特别的. Player是一个简单的容器对象包含三个属性:玩家名字,游戏名字,他游戏的评级(1-5星)。在App Delegate中你需要为这个数组创建一些测试的Player对象,并且把它分配给PlayersViewController的players 属性。在AppDelegate.m中,在文件顶部为Player和PlayersViewController添加#import,并且添加一个实例变量_players,如下图:
  1. #import"AppDelegate.h"
  2. #import"Player.h"
  3. #import"PlayersViewController.h"
  4. @implementationAppDelegate
  5. {
  6. NSMutableArray*_players;
  7. }
  8. //Restoffile...
修改application:didFinishLaunchingWithOptions: 方法,如下图
  1. -(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions
  2. {
  3. _players=[NSMutableArrayarrayWithCapacity:20];
  4. Player*player=[[Playeralloc]init];
  5. player.name=@"BillEvans";
  6. player.game=@"Tic-Tac-Toe";
  7. player.rating=4;
  8. [_playersaddObject:player];
  9. player=[[Playeralloc]init];
  10. player.name=@"OscarPeterson";
  11. player.game=@"SpintheBottle";
  12. player.rating=5;
  13. [_playersaddObject:player];
  14. player=[[Playeralloc]init];
  15. player.name=@"DaveBrubeck";
  16. player.game=@"TexasHold’emPoker";
  17. player.rating=2;
  18. [_playersaddObject:player];
  19. UITabBarController*tabBarController=(UITabBarController*)self.window.rootViewController;
  20. UINavigationController*navigationController=[tabBarControllerviewControllers][0];
  21. PlayersViewController*playersViewController=[navigationControllerviewControllers][0];
  22. playersViewController.players=_players;
  23. returnYES;
  24. }
我们创建了一些 Player 对象并且把它们加到了_players 数组中,接下来:
  1. UITabBarController*tabBarController=(UITabBarController*)self.window.rootViewController;
  2. UINavigationController*navigationController=[tabBarControllerviewControllers][0];
  3. PlayersViewController*playersViewController=[navigationControllerviewControllers][0];
  4. playersViewController.players=_players;
嗯?!我们想把_playersarray分配给PlayersViewController的playersproperty,那样它才能把这个数组作为它的datasource,但是 app delegate并不知道PlayersViewController是什么玩意,它会通过storyboard找到它。注意:这是storyboard的一个限制。用nib的时候你需要在AppDelegate 中指定MainWindow.xib 的引用,你可以通过连接顶层的视图控制器到你的AppDelegate中。在storyboard里,这是不可能的,你不能在appdelegate中为你的顶层视图控制器做引用,这很不幸,所以我们一般都手动的写,就像你现在做的这样。让我们一步一步来
  1. UITabBarController*tabBarController=(UITabBarController*)self.window.rootViewController;
你知道 storyboard最初的viewcontroller 是一个Tab Bar Controller,所以你可以指定window的rootViewController 为UITabBarController.在第一个tab中,PlayersViewController位于navigationcontroller,所以你首先要查询UINavigationController 对象,代码如下:
  1. UINavigationController*navigationController=[tabBarControllerviewControllers][0];
然后获取它的root view controller,这里是PlayersViewController:
  1. PlayersViewController*playersViewController=[navigationControllerviewControllers][0];
为storyboard制作你想要的视图控制器看来是需要花一些时间的,当然了,如果你想换tab的顺序,或者当前应用不是以tab barcontroller 作为 rootviewcontroller了,你将不得不修改这个逻辑。现在我们有了一个包含Player对象的数组了,我们可以为PlayersViewController创建datasource了。打开PlayersViewController,在顶部添加import:
  1. #import"Player.h"
修改 table view data source方法如下
  1. -(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
  2. {
  3. return1;
  4. }
  5. -(NSInteger)tableView:(UITableView*)tableViewnumberOfRowsInSection:(NSInteger)section
  6. {
  7. return[self.playerscount];
  8. }
真正的操作发生在cellForRowAtIndexPath 中,起初方法如下:
  1. -(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath
  2. {
  3. staticNSString*CellIdentifier=@"Cell";
  4. UITableViewCell*cell=[tableViewdequeueReusableCellWithIdentifier:CellIdentifier];
  5. if(cell==nil){
  6. cell=[[UITableViewCellalloc]initWithStyle:UITableViewCellStyleDefault
  7. reuseIdentifier:CellIdentifier];
  8. }
  9. //Configurethecell...
  10. returncell;
  11. }
你需要问你的table view列出一个cell,如果它返回nil则说明当前并无可重用的cell,所以你需要自己创建一个新的cell类实例,毫无疑问这需要你手写代码了,用以下方法代替:
  1. -(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath
  2. {
  3. UITableViewCell*cell=[tableViewdequeueReusableCellWithIdentifier:@"PlayerCell"];
  4. Player*player=(self.players)[indexPath.row];
  5. cell.textLabel.text=player.name;
  6. cell.detailTextLabel.text=player.game;
  7. returncell;
  8. }
这看起来很简单,你只需要像下面获取cell
  1. UITableViewCell*cell=[tableViewdequeueReusableCellWithIdentifier:@"PlayerCell"];
如果当前没有一个可以重用的cell它会自动返回一个prototype cell 的copy 并且返给你。下面你就需要使用在storyboard编辑器中设置的re-useidentifier,这里是"PlayerCell"运行应用,table view如下图所示:仅仅需要一行代码就可以实现这个新奇的prototypecells。注意:这个应用我们只用到了一种prototype的cell,如果你想用更多种类的cell,只需要简单地把那些额外的prototypecell 加到storyboard上,你也可以复制当前存在的cell 去做一个新的,或者增加当前table view的Prototype cell的属性,但是要确保一点,每个cell都需要有一个只属于它自己的re-useidentifier设计你自己的PrototypeCells很多app 都是使用 默认的cellstyle的,但是对于这个应用,cell的右侧有一个图片用来显示这个用户的得分(从1星到5星),默认的cell不带这种具有image的style,所以这里我们需要自己设计一个。回到Main.storyboard,选择table view中的prototype cell并把它的Style attribute 设置为Custom,默认的labels 现在没有了。第一步把cell稍微加高一点,通过拖拽它的下边,或者改变Size inspector中的Row Height值都可以。 把cell的高度设置为55points。从Objects Library 拽2个 Label 到cell 上, 把他们放在刚才那个label所在的地方,随便改改颜色 字图或者写点什么都行。拖一个Image View到cell上,并让它居于cell的右侧,紧挨着disclosure indicator 设置它的Mode 为 Center(在Attributes inspector的view 下面),这样无论你防止什么样的图片到这个Imageview上它都不会被拉伸。设置 labels 的宽度为190 points这样他们就不会挡住image view。最终的效果如下图所示:因为这是一个自定义cell所以你再也不需要UITableViewCell 中的textLabel和detailTextLabel属性来设置text。因为这些属性指向的labels 在这个cell中并不存在了。作为替代,你需要使用tags 来找到这些labels。给Name label 的tag设置为100,Game 的label 设置为101,Image View 的tag设置为102,通过Attributesinspector 可以找到。下面打开PlayersViewController.m增加一个方法,imageForRating:.如下:
  1. -(UIImage*)imageForRating:(int)rating
  2. {
  3. switch(rating){
  4. case1:return[UIImageimageNamed:@"1StarSmall"];
  5. case2:return[UIImageimageNamed:@"2StarsSmall"];
  6. case3:return[UIImageimageNamed:@"3StarsSmall"];
  7. case4:return[UIImageimageNamed:@"4StarsSmall"];
  8. case5:return[UIImageimageNamed:@"5StarsSmall"];
  9. }
  10. returnnil;
  11. }
把tableView:cellForRowAtIndexPath: 改成:
  1. -(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath
  2. {
  3. UITableViewCell*cell=[tableViewdequeueReusableCellWithIdentifier:@"PlayerCell"];
  4. Player*player=(self.players)[indexPath.row];
  5. UILabel*nameLabel=(UILabel*)[cellviewWithTag:100];
  6. nameLabel.text=player.name;
  7. UILabel*gameLabel=(UILabel*)[cellviewWithTag:101];
  8. gameLabel.text=player.game;
  9. UIImageView*ratingImageView=(UIImageView*)[cellviewWithTag:102];
  10. ratingImageView.image=[selfimageForRating:player.rating];
  11. returncell;
  12. }
下面运行app ,效果如下:哎呦~,看起来不怎么对哈,这些cell都重叠在一起了,你只改变了prototype cell的高度,但是并没有把table view考虑进去。这里有2个解决方案,1改变tableview 的Row Height 属性或者执行tableView:heightForRowAtIndexPath:注意:你可能需要hightForRowAtIndexPath,如果你不知道你的cell的具体高度,或者不同的行有不同的高度。.回到Main.storyboard,在Table View的Sizeinspector设置Row Height 为55:再运行app,看起来好多了。顺路说一嘴,当你通过拖拽cell下沿的方式而不是直接设置值的方式去改变cell的高度,那么table view 的row高度属性自动会变,当你第一次这么做的使用它就会好用。Using a Subclass for theCell这个table view已经看起来相当不错了,但我对于通过tag 去获取 label 或者 这个cell 的其他子视图不感冒,把这些labels与类的outlet连接起来并使用相应性应该是更好的方式,事实证明你可以。通过Objective-C classtemplate为项目添加一个新文件,命名为PlayerCell,并使它继承自,继承自UITableViewCell:
  1. @interfacePlayerCell:UITableViewCell
  2. @property(nonatomic,weak)IBOutletUILabel*nameLabel;
  3. @property(nonatomic,weak)IBOutletUILabel*gameLabel;
  4. @property(nonatomic,weak)IBOutletUIImageView*ratingImageView;
  5. @end
这个类本身并没有做什么事情,仅仅是增加了几个属性nameLabel,gameLabel以及ratingImageView,并且是Outlets。回到Main.storyboard,选中prototypecell,并在Identity inspector中把它的class改成PlayerCell。现在无论什么时候你通过dequeueReusableCellWithIdentifier向tableview请求一个新的cell时,它会返回PlayerCell实例而不是UITableViewCell。注意:这里我们把类名跟reuse identifier设置成一样了,PlayerCell 这只是我的习惯而已,类名跟reuse identifier并没有什么关系,所以如果你想起不一样的,随你好了。下面连接 labels 以及 imageview的outlet,选择label的onnections inspector 中的New Referencing Outlet 拖拽到table view cell 上,分别选中nameLabel ,gameLabel:重点:你需要把controls与table view cell连接起来,而不是视图控制器。当你的data source 要求那个table view通过dequeueReusableCellWithIdentifier 要一个新的cell 的时候,table view并不是给你一个真实的prototypecell,而是复制一份给你(或者重用之前那些cell中一个也说不定)。这就意味着在同一时间不止有一个PlayerCell的实例。然后不同的label拷贝视图访问一个outlet,这是自找麻烦(从另一方面,把prototype cell 的 actions连接到视图控制器上是可行的,当你的cell 中有自定义按钮或者是其他继承于UIControls )现在你已经连接好这些属性了,你只需要写点点datasource代码。首先在PlayersViewController.m中引入PlayerCell 类:
  1. #import"PlayerCell.h"
然后把cellForRowAtIndexPath改为:
  1. -(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath
  2. {
  3. PlayerCell*cell=(PlayerCell*)[tableViewdequeueReusableCellWithIdentifier:@"PlayerCell"];
  4. Player*player=(self.players)[indexPath.row];
  5. cell.nameLabel.text=player.name;
  6. cell.gameLabel.text=player.game;
  7. cell.ratingImageView.image=[selfimageForRating:player.rating];
  8. returncell;
  9. }
更喜欢它了吧,现在你通过dequeueReusableCellWithIdentifier获取PlayerCell的实例,然后可以设置 它的 labels 以及imageview。运行应用,它看起来跟之前没什么不同,但是要注意到,你现在已经用的是自定义的tableviewcell 的子类了。

  

爱华网本文地址 » http://www.aihuau.com/a/25101016/305480.html

更多阅读

Word教程-在Word中如何使用通配符快速查找 word快速查找

Word教程-在Word中如何使用通配符快速查找——简介若要想在Word中使用通配符来调整搜索条件,依次单击“编辑→查找”,或者可以按组合键Ctrl+H弹出“查找和替换”对话窗口进行设置,下面我跟大家说说在Word中如何使用通配

在EDK中使用DDR2内存的仿真方法 ddr2有4g内存条吗

Micron的网站上可以下载到DDR2的仿真模型,开始以为直接连上就好,但事实上问题很多。1.DDR2模型配置DDR2仿真模型文件很多,其本身就是一个可以运行的仿真模块。我们不需要那么多文件,需要用到的文件是:Ddr2.v是内存颗粒的仿真文件,ddr2

凭证中使用红字和负数是根本性的错误 红字发票与负数发票

2011年初,我们写过一篇“关于会计中的红字和负数”,最后有一个结论:在凭证中使用红字和负数是完全错误的。2012年初我们发布了财务系统后,仍然经常有人在讨论这个问题,很多朋友说很难对本公司的会计解释这些,因为在凭证中使用红字和负数是

地被植物在园林中的应用及研究现状 常见园林地被植物

(2006-06-09 17:16:57) 转载摘要:探讨了地被植物的内涵,调查了浙江省园林中常见的多年生草本地被植物,并提出了一些未在园林中应用的观赏价值较高的野生及彩叶地被植物,初步探讨了地被植物的研究方向。地被植物在园林中,是一个不可缺少的

声明:《在iOS7中使用storyboardpart1 及prototypecell使用 storyboard cell 重用》为网友帅的好烦躁分享!如侵犯到您的合法权益请联系我们删除