![ea961ace06d0add2d477db5e32502eaf.png](https://i-blog.csdnimg.cn/blog_migrate/de5952b4854f47320d01975387c69510.jpeg)
说明:
本系列教程改编自raywenderlich.com中的iOS Apprentice系列,有需要的童鞋请移步到这里购买英文版原教程:https://store.raywenderlich.com/products/ios-apprentice
欢迎继续我们的学习。
在上一课的内容中,我们已经成功的显示出了表格,然后遗憾的是看不到其中有任何数据。
在本课的内容中,我们将一起学习如何完成这个伟大的使命。
哪怕地球在流浪,依然要努力~
表视图代理
打开项目,切换到ChecklistViewController.swift,然后在文件的底部添加以下代码:
//MARK:- Table View Data Source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath)
return cell
}
比起上一系列内容中的代码,这两个方法看起来似乎有点吓人。因为每个方法都有两个参数,而且还返回了一个值。不过除了这种有点恐怖的形式之外,其实这两个方法的作用跟我们之前所接触过的并没有什么本质区别。
协议(Protocols)
以上两个方法其实都属于UITableView的data source 协议。
那么什么是协议呢?
首先来看作为法律术语的协议。在日常生活中,协议跟合同经常混用,指的是双方通过法律认同的方式达成了某种共识,并需要在法律的框架下遵守。
此外,在技术领域,对互联网比较熟悉的童鞋可能听说过各种通讯协议,比如Ethernet协议、TCP/IP协议,UDP协议、Zigbee协议等等。这里的协议指的是通讯双方所必须遵从的一组约定,比如如何建立连接,如何相互识别,等等。
那么在iOS开发中的协议又指的是什么呢?
这里的协议指的是某个类必须支持的一系列标准方法。通过设置这种协议,某个指定的类需要用一种特定的方式(指定类型的参数和返回值)来实现一系列的方法,但同时作为开发者又无需知道具体的实现细节。
通过使用协议,开发者可以给某个类添加某种特定类型的操作,比如这里让表视图可以来处理数据。
data source(数据源)是数据和表视图之间的桥梁。通常来说,在iOS开发中视图控制器会扮演数据源的角色,并实现所需要的方法。因此,可以说视图控制器就是表视图的”代理“。
这就是所谓的代理模式-某个对象代表另外一个对象来完成某项任务。
表视图需要知道它所需处理的数据行数,以及如何显示某一行数据。但是我们并不能简单的把一堆数据塞到表视图的手里,然后命令它,”表视图,这里有100行数据,帮忙把它们显示在屏幕上吧。“
实际上,我们只能跟表视图商量,“视图控制器现在就是你的数据源。所以,你最好问问它该怎么显示。”
而一旦表视图关联到某个数据源上-比如这里的视图控制器,那么它就会发送一个numberOfRowsInSection消息,来询问有多少行数据需要显示。
而接下来表视图会发送一条cellForRowAt消息,向数据源请求获取某个具体的数据,从而显示在cell里面。
在iOS开发的学习中,我们将逐渐习惯看到这种模式:某个对象代替另外一个对象来完成某些任务。比如,在这里ChecklistViewController将向表视图提供所需的数据,不过前提是表视图提出了这样的请求~
![d9b0b5a16ebc853a9186e0ecd0f85951.png](https://i-blog.csdnimg.cn/blog_migrate/e32b8c5c3e55d8c29d32e281e0d76ccb.jpeg)
在我们刚才所实现的第一个方法,也就是tableView(_: numberOfRowsInSection:)返回了一个数值1,它的作用是通知表视图,只需要显示一行数据。
在Swift语言中,return语句非常非常重要。
通过return语句,我们可以向方法的调用者回传一个数据。比如在tableView(_:numberOfRowsInSection)这个方法中,调用方法的是UITableView对象,它需要知道在表中究竟要显示多少行数据。
方法体内的语句通常会利用实例变量以及从参数中所获取的数据进行某些运算。当方法体内的代码执行完成后,return返回语句就会告诉系统,“任务完成,这里是我得出的结论。”所返回的值通常被称之为方法的结果。
对tableView(_:numberOfRowsInSection:) 这个方法来说,答案很简单:只有一行数据需要显示,因此返回1.
现在表视图已经知道它需要显示一行数据了,那么接下来就需要调用第二个方法,也就是tableView(_:cellForRowAt:)
通过这个方法,表视图获取了一个原型cell的拷贝,然后将其返回给表视图。可以看到,这里再次用到了return语句。
在tableView(_:cellForRowAt:) 语句中,同时我们也会将行数据放入到cell中,不过目前应用中还没有任何的数据。
好了,点击工具栏上的运行按钮,可以看到界面上终于有了第一行数据。
![2fd7cbcac83f00e5fcad2fcb63028499.png](https://i-blog.csdnimg.cn/blog_migrate/c81823d8c416e8b8a29ec341d51ce331.jpeg)
小练习:
如果我们想让表格中显示五行数据,该怎么办呢?
狠简单,
把tableView(_:numberOfRowsInSection:) 的返回值改为return 5就好了,试试看?~
![c68c14af6d364696295ae1ea9b30d6fd.png](https://i-blog.csdnimg.cn/blog_migrate/a29de5ba2012643861075da2e282cd30.jpeg)
理论知识:关于MVC
在结束本课之前,让我们再充点电,了解下MVC模式。
实际上,在学习刚才的代理(delegate)和协议(protocols)用法的时候,可能很多童鞋都会质疑:
为什么要这么麻烦呢?为什么要让视图控制器来提供数据,而不是干脆让表视图自己给自己提供数据呢?这样就不需要所谓的代理和协议了,多方便~
是啊?为什么呢?
原因是,iOS应用的开发遵循非常严格的MVC(Model-View-Controller)模式。也就是模型-视图-控制器模式。
在MVC模式下,表视图只不过是一种纯粹的视觉元素(也就是视图),它不能也不应该和具体的数据扯上边。数据通常是在Model那里,我们只有通过controller视图控制器这个桥梁把视图和数据模型关联起来。
如果你曾经学过其它编程语言和框架,会发现iOS的开发模式是最符合MVC的,逻辑上也是最清晰的。
那么MVC模式有什么好处呢?
MVC模式可以把业务逻辑(通常由controller负责)、数据(model)和界面显示(view)严格区分开来,这样在改进和个性化定制界面,或是对数据进行修改时,不需要把所有的内容都重写。
此外,MVC模式允许使用各种不同的视图来访问同一个数据源,并在不同的终端界面中使用。
其实除了在iOS开发中用到了MVC模式,在web开发中也经常用到MVC模式。
当然,除了经典的MVC架构模式,现在还有了几种新的变种,比如MVP(model-view-presenter)、MVVM(Model-view-viewmodel)和Viper,感兴趣的童鞋可以自行了解:
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel
https://www.objc.io/issues/13-architecture/viper/
最后要再次安利一下斯坦福大学的iOS开发公开课,里面对MVC模式做了非常详尽而直观的解释,强烈推荐e文好的童鞋前往观看~
![30626a822327d79bb7ccca8682e17024.png](https://i-blog.csdnimg.cn/blog_migrate/aef6d8d1496b3279d48fc7b2fd373436.jpeg)
答疑说明:
大家后续有开发相关的问题请到课程答疑专区提问http://icode.fun/ask/forum.php
公众号:icodefun