【IOS】从android角度来实现(理解)IOS的UITableView

简介:

以下内容为原创,欢迎转载,转载请注明

来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3403124.html

 

本人从在学校开始到现在上班(13年毕业)一直做web和android方面的开发,最近才开学习及ios的开发,所以ios学习中有不当之处,请大家留言赐教啦

以前从来没有接触过Objective-C这门语言,不过我想面向对象编程应该大体思想都差不多

在ios中的UITableView学习中,开发过android的朋友应该马上会联想到ListView和GridView这两个控件,接下来以ListView为例子,跟UITableView做个对比,看看它们实现的方式有什么相同之处。怎么样能让有android开发经验的朋友,马上掌握UITableView这个控件

先新建一个demo,取名TabViewTest(原谅我吧- -,本来要取名TableViewTest,谁知脑抽新建项目的时候写错了,诶。。。算了,将错就错吧- -)

ios没有命名空间的概念,没有包概念(这也是为什么ios中的类都有前缀的原因,比如NS等),所以上面像“包”一样的文件夹都是我自己新建的“group”,只是为了看起来比较有分层的概念而已,打开finder,到项目文件里一看如下图,妈呀- -,所有的类都挤在一个文件夹里面。。。这是我觉得蛋疼的地方之一-。-

 

再回来看看我们项目结构,我分的几个group,如果我把controller这个group的名字改成“activity”,android开发者肯定有种似曾相识的感觉了:

controller:控制层group,相当于android中的activity

layout:布局group,相当于android中res目录下的layout(xml布局文件)

model:这个不用说就知道放了什么东西了,经典的Person这个测试用的数据结构

adapter:为了还念android中的适配器,然后我就取了这么个group名字

 

好了,现在正式开始代码的编写

打开MainAppDelegate.m,它实现了UIApplicationDelegate协议,所以可以在该类中实现应用状态的回调函数

在application:didFinishLaunchingWithOptions:方法(应用程序启动时回调该方法)中来设置它的RootController(根控制器,不知道这样翻译专不专业- -),我的实现是生成一个UINavigationController作为它的root controller,然后把自己新建的一个NaviRootController(在这个Controller中放入一个UITableView,具体下面会讲到)作为UINavigationController的root view,具体代码如下(这个不是我们本次的重点,所以一笔带过):

复制代码
 1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 2 {
 3     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
 4 
 5     // 生成UINavigationController对象,并设置它的RootController
 6     UINavigationController *naviController = [[UINavigationController alloc] initWithRootViewController:[[NaviRootController alloc] init]];
 7     // 然后把NavigationController设置为window的RootViewController
 8     [self.window setRootViewController:naviController];
 9     
10     self.window.backgroundColor = [UIColor whiteColor];
11     [self.window makeKeyAndVisible];
12     return YES;
13 }
复制代码

然后,重点就是NaviRootController这个Controller了,

新建NaviRootController,继承UIViewController,在.h文件中:

声明一个NSMutableArray对象data作为tableView的数据源(相当于在android中经常用到的ArrayList<Person> data。NSMutableArray是数组,ArrayList在java中的底层实现本来用的就是数组,所以很好理解

声明一个用于适配和绑定tableView数据的适配器TableViewAdapter *adapter(这个类是我自己写的,下面会讲到。java中要实现ListView中的数据绑定适配,也要通过一个继承于BaseAdapter的适配器进行数据的适配吧,也很好理解

声明一个UITableView对象(相当于android中,在activity中声明一个private ListView listView;

具体代码如下:

  View Code

好了,声明部分到此为止,接下来看看实现部分

刚刚在MainAppDelegate中,生成了一个NaviRootController对象,然后把这个对象加入到了UINavigationController对象的rootViewController。生成NaviRootController对象的时候,调用了init方法,我们应该在init方法里面去初始化布局,如下:

  View Code

我们在init方法中调用了initWithNibName:bundle:方法,传入了NibName这个字符串,这个是什么?Nib是ios里面的布局文件,也就是相当于android中类似main.xml这种布局文件吧,现在传进去的时nibname,也就是布局文件的名称。所以,没错,传入这个参数后,当前的controller(也就是NaviRootController就跟传入的这个布局文件绑定起来了,类似于android中activity中熟悉的setContentView(R.layout.main)一样!

然后我们顺便看看navi_root.xib这个布局文件:

整个界面就一个UITableView,对了,别忘了在File's Owner中把custom class改成NaviRootController。键盘按住control,用鼠标拖动左边栏的“Table View”到NaviRootController.h中,会自动生成UITableView声明,并自动绑定。

接下来回到NaviRootController的初始化方法中。

initWithNibName:bundle:方法中后面的UINavigationItem相关的代码是用来设置导航栏左边和右边的按钮,既然是个demo,所以也没什么特别的功能,就是点击下,跳出一个UIAlertView提示下,所以一笔带过。

此时界面布局和controller已经绑定起来了,现在的任务应该是初始化UITableView的数据,也就是上面的data属性,但是在哪里初始化比较好呢?

刚开始,我是直接在init方法中直接去初始化数据,但是失败了,不管在init方法中初始化多少次(data调用多少次addObject方法),data的值永远都是nil(相当于在android中,不管调用多少次list.add(...)方法,list中一条数据也没有加入!),猜测是因为在init方法中的时候属性和控件都还没有被初始化。

最后我的解决办法就是在viewDidLoad方法中去加载数据。viewDidLoad这个回调方法是会在控件加载完毕后调用,所以,我认为在这里去加载数据和做控件的初始化操作是比较合理的。

viewDidLoad方法实现如下:

  View Code

如上,在viewDidLoad中,我先去初始化数据(demo中的实现其实就是循环了14次,往data中加了14个Person对象),然后生成一个适配器委托对象,传入data(数据源)和self(当前controller对象),相当于android中的 adapter = new MyAdapter(list, this);有木有??!!

然后,setDelegate用来设置委托对象(相当于android中的listView.setAdapter(adapter)),setDataSource用来设置数据源。

这里,完整地列出NaviRootController的代码:

  View Code

 

好了,UITableView的初始化准备工作到此就做完了,现在干嘛?

当然去编写TableViewAdapter这个类啊。数据源有了(并且初始化完毕),用以显示的控件(UITableView)有了(并且初始化完毕),而且两个还已经绑定起来了。但是还缺的就是一个角色,这个角色可以把数据源中的数据跟控件中某个相应的子控件适配起来。比如数据源中有4个数据,A、B、C、D,控件有one、two、three、four这4个控件,这个角色的任务就是告诉one:你要显示的数据是A;告诉two:你要显示的数据是B;告诉three:你要显示的数据是C;告诉four:你要显示的数据是D!

这个角色就是适配器!也就是下面要说的那个TableViewAdapter

新建TableViewAdapter,实现<UITableViewDataSourceUITableViewDelegate>这两个协议(android中适配器不同的是要继承BaseAdapter类)。声明一个数据源data,这个数据源是从NaviRootController中传过来的已经初始化好了的数据源,还有一个声明是NaviRootController对象传过来的self(需要什么,就让调用者传什么过来,这个应该都懂的-。-),另外还有一个自己写的初始化方法(自己写初始化方法init打头的方法就行,不像java中的构造方法,方法名要跟类名相同,不过这些都是换汤不换药)

然后看看TableViewAdapter的实现类(.m)

实现了这两个协议后,你就能覆写里面的一些UITableView的回调方法了,比如:

tableView:numberOfRowsInSection:方法,返回数据源的数量就行了(类似android的adapter中自己要实现的getCount()方法!

tableView:cellForRowAtIndexPath:这个是方法是这里最关键的一个方法了,就是在这里进行数据的适配工作(类似android的adapter中自己要实现的getView()方法!),这里返回的UITableViewCell就是类表中的一项(类似android中listview的一个item),这个一项的布局,已经在table_cell.xib文件中布局完毕,如下:

设置File's Owner为TableViewAdapter,设置Table View Cell的identifier设置为“MyTableCell”,这个可以任意取名,但是要跟后面的方法实现中统一(跟哪里统一?作用是神马?这些下面会讲到,别急-。-),接着设置ImageView的tag为1,nameLabel的tag为2,ageLabel的tag为3(tag的作用,下面也会讲到)。

接着,回到tableView:cellForRowAtIndexPath:这个方法,它的实现如下所示:

复制代码
 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     Person *p = [data objectAtIndex:[indexPath row]];
 4     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyTableCell"];
 5     if (!cell) {
 6         NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:@"table_cell" owner:self options:nil];
 7         cell = [nibViews objectAtIndex:0];
 8     }
 9 
10     UIImageView *picIv = (UIImageView *)[cell viewWithTag:1];
11     UILabel *nameLb = (UILabel *)[cell viewWithTag:2];
12     UILabel *ageLb = (UILabel *)[cell viewWithTag:3];
13     
14     [nameLb setText:[p name]];
15     [ageLb setText:[NSString stringWithFormat:@"%d", [p age]]];
16     [picIv setImage:[p pic]];
17     
18     return cell;
19 }
复制代码

如上图所示:

第3行,是用于获得所要显示的数据Person对象(这里的[indexPath row]相当于android的adapter的getView方法的position参数。indexPath中有两个参数,row和section,表示行和列,因为我们现在是要显示一个列表,所以只需要row这个参数就可以了)

第4行,是用于资源的重复利用,根据标示符“MyTableCell”去获得一个可再利用的UITableViewCell(这里的标示符就要跟前面在xib文件中设置的标示符要一致,这样才能被识别到,然后在这里被获取到),如果没有获得到,就去新创建一个UITableViewCell。

第6、7行,是创建新的UITableViewCell的代码,通过mianBundle的loadNibNamed:owner:options方法根据xib的名字去创建(android中的LayoutInflater.inflate()方法通过R.layout.xxx的方法创建类似),loadNibNamed:owner:options返回的是一个数组,得到第一个就是UITableViewCell了。

第10、11、12行,是获取到或者新建的cell通过控件之前设置的tag来获得相应地子控件(现在知道之前为什么要设置xib文件中控件的tag了吧?这个跟android中的findViewByTag/findViewById又是很类似的!

第14、15、16行,是为刚刚获得的cell中的子控件适配数据,让它可以把数据显示出来。

第18行,把生成数据适配完毕的UITableViewCell返回出去(这跟android中的也是很类似

TableViewAdapter代码如下:

  View Code

 

好了!到此为止整个UITableView实现的流程基本完成了,可以看出跟android的ListView和GridView的实现流程很相似,理解了其中一个,另一个也能很好的理解它的工作流程。

最后来一张效果图:

本文转自天天_byconan博客园博客,原文链接:http://www.cnblogs.com/tiantianbyconan/p/3403124.html ,如需转载请自行联系原作者
相关文章
|
4天前
|
IDE 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔舞台上,安卓与iOS这两大操作系统各占半壁江山。它们在开发环境上的差异,不仅影响了开发者的编码体验,也在一定程度上塑造了应用生态的多样性。本文将深入探讨两者在开发工具、编程语言、用户界面设计以及市场分布等方面的不同特点,为即将踏入这一领域的开发者提供一盏明灯。
|
4天前
|
IDE 开发工具 Android开发
安卓与iOS开发环境的差异性分析
在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各据一方,引领着市场潮流。它们各自拥有独特的开发环境和工具集,为开发者提供了不同的挑战与机遇。本文旨在深入剖析这两个平台的开发环境,通过比较它们的编程语言、集成开发环境(IDE)、用户界面设计、以及系统架构等方面,揭示各自的优势与局限。我们将探讨如何基于这些差异来优化开发策略,并预测未来可能的发展趋势,以期为开发者在选择平台时提供有价值的参考。
|
3天前
|
前端开发 Android开发 iOS开发
探索安卓与iOS开发的差异性与互补性
在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统各据一方,引领着市场潮流。它们在技术架构、开发环境及用户群体等方面展现出独特的差异性,同时也存在着潜在的互补性。本文将深入剖析这两种平台的开发细节,从不同角度揭示其各自优势及相互之间的协同潜力,为开发者提供全面而深刻的视角。
10 2
|
4天前
|
开发工具 Android开发 iOS开发
探索Android与iOS开发环境的差异性
在移动应用开发的广阔天地中,Android和iOS两大平台如同双子星座般耀眼。本文将深入探讨这两个操作系统的开发环境,揭示它们在编程语言、工具、用户界面设计以及性能优化等方面的显著差异。通过对比分析,旨在为开发者提供清晰的平台选择指导,并帮助他们理解各自环境下的最佳实践。
|
4天前
|
API 开发工具 Android开发
安卓与iOS开发环境对比分析
移动操作系统的两大巨头,安卓和iOS,各自拥有独特的开发环境和工具。本文将深入探讨两者的开发环境差异,从编程语言、开发工具、用户界面设计、API支持以及生态系统五个维度进行比较分析。通过数据支撑和案例研究,揭示各自的优势和局限性,为开发者选择适合自己项目需求的平台提供参考依据。
13 1
|
4天前
|
IDE API Android开发
安卓与iOS开发环境的差异及适配策略
在移动应用开发的广阔舞台上,Android和iOS两大操作系统各据一方,各自拥有独特的开发环境和工具集。本文旨在深入探讨这两个平台在开发环境上的关键差异,并提供有效的适配策略,帮助开发者优化跨平台开发流程。通过比较Android的Java/Kotlin和iOS的Swift/Objective-C语言特性、IDE的选择、以及API和系统服务的访问方式,本文揭示了两个操作系统在开发实践中的主要分歧点,并提出了一套实用的适配方法,以期为移动开发者提供指导和启示。
|
10天前
|
Java Android开发 iOS开发
探索安卓与iOS开发的差异性与互操作性
【7月更文挑战第17天】在移动应用开发的广阔天地中,安卓和iOS这两大操作系统如同双子星座般璀璨夺目。它们各自拥有独特的开发环境、编程语言和用户群体,为开发者提供了不同的挑战和机遇。本文将从多个维度深入剖析安卓与iOS开发的差异性,并探讨它们之间的互操作性如何实现,以期为开发者们提供一份实用的指南。
24 7
|
7天前
|
Java Android开发 iOS开发
探索安卓与iOS开发的差异:平台特性与用户体验的对比分析
【7月更文挑战第19天】在移动开发的广阔天地中,安卓与iOS两大阵营各据一方,它们在开发环境、用户界面设计、性能优化等方面展现出独特的魅力与挑战。本文旨在深入探讨这两个平台在技术开发和用户体验上的根本差异,并分析这些差异如何影响开发者的策略和最终用户的选择。通过比较两者的编程语言、工具、框架以及设计理念,我们将揭示各自平台的优势与局限,为开发者提供实用的参考,并为消费者呈现一个更加清晰的平台选择视角。
|
9天前
|
安全 Java Android开发
探索安卓与iOS开发的差异:构建未来应用的关键考量
【7月更文挑战第18天】在移动应用开发的广阔天地中,安卓和iOS两大平台各领风骚。本文将深入探讨这两个平台在开发过程中的主要差异,包括编程语言、用户界面设计、性能优化、安全性以及市场策略等方面。通过比较分析,旨在为开发者提供决策支持,帮助他们选择最适合自己项目需求的平台,同时考虑到用户体验和市场需求的变化,为未来的应用开发指明方向。
|
9天前
|
安全 开发工具 Android开发
安卓与iOS开发环境对比分析
本文通过深入探讨和比较安卓与iOS两大主流移动操作系统的开发环境,旨在为开发者提供一个全面的视角。我们将从开发工具、编程语言、用户界面设计、性能优化、安全性考量等多个维度进行细致分析,揭示各自平台的优势与挑战。通过统计数据支持的实证研究,本文将展示两个系统在实际应用中的技术差异及其对项目开发周期的影响,并基于市场数据评估各自的商业潜力。
15 1