专业完整版请参考(www.appcoda.com/learnswift/)
上面网址的教程文档为试用版,需要购买。(支持正版从我做起💪)
各位看官注意啦,本文章不是教程,只是我的一个分享而已,有错误还请指出。
本人也只是一个刚学习的小白而已,写文章是想起到回顾和记录作用,同时也给大家分享一下。 如果哪里有错误,还请大家指正。
本文基于iOS12和Xcode10
前言
首先我们要做的是先介绍一下什么是Navigation Controllers。
就像我们之前讲到的table view一样,navigation controller同样也是一个在iOS应用程序中的其他常见UI组件,同时提供了一个向下钻取的界面。 通常而言,我们会把tableview和navigation controller组合在一起构建一个非常漂亮的界面。但不意味着你必须同时使用这两者,navigation controllet可以使用任何类型的视图控制器。
关于storyboards
直到目前为止,我们在App的故事板上仅仅只有一个视图控制器。我们可以添加多个视图控制器然后使它们链接在一起,在定义它们之间的过渡元素。这些操作我们都可以在不添加一行代码的情况下完成。
但我们使用故事板时,有两个条款需要我们明白分别是scene和segues。
Scene通常指的是屏幕上的内容(比如一个视图控制器)
Segues位于两个场景之间,代表一个场景到另一个场景的过渡。Push和Modal是两种比较常见的过渡类型。
创建 Navigation Controller
我们将通过把列表视图控制器嵌入navigation controller来继续处理我们的项目。当我们点击任意一个餐厅时,就跳转至另一个屏幕显示这个餐厅的细节。 (github.com/x1700209131…)
Xcode有个很好用的功能方便你嵌入任意一个视图控制器在navigation controller中。 选中Main.storyboard并切换到Inertface Builder,在选中table view controller 并点击菜单中的Editor。选择Embed in > Navigation Controller


更大的导航栏标题
在iOS 11之后,迎来的更大导航栏标题。但是它的大小并不固定,当你滑动视图中的内容时,它的标题将会缩小到原来一样。
在默认情况下,更大的标题是没有开启的。如果你想在导航栏里使用更大的标题,你需要插入代码在RestaurantTableViewController类的ViewDidLoad()方法中以下代码:
navigationController?.navigationBar.prefersLargeTitles = true
再次运行你的app。
添加细节视图控制器
现在我们的app已经有了一个导航栏,但是我们还缺少一个显示餐厅细节的视图控制器。当用户点击餐厅的时候,app将转换到详细视图控制器并显示餐厅详细信息。这就是我们将要完成的任务。
在 Interfacce BUilder中,从Object libraty中拖动视图控制器(view controller)来创建一个细节控制器。 我们要细节视图中尽可能保持简单,仅仅显示餐厅照片就好。拖动图像视图到视图控制器中,并调整大小至铺满全部且添加好约束距离。 为了保证图片的正确缩放,在Attributes inspector中找到mode改变其中的格式为Aspect Fill
现在我有table view controller和 detail view controller在我们的故事板中。现在的问题是我们如何将他们链接在一起。在故事板中,我们链接它们需要通过Segue。
当用户点击单元格时,列表视图控制器将转换到详细信息场景所以我们要添加Segue来链接原型单元格和细节场景。按住Control键,从Detail View Controller 拖拽到单元格(列如: datacell)上,并选择Show

- Show -当我们选中Show这个格式的时候,内容将会被自动的推送到视图控制器的顶部。导航栏将显示一个返回按钮,用来返回原始的视图控制器。
- Show detail -这是一个类似于Show的格式,但是细节图控制器中的内容替换了当前视图控制器堆栈的顶部。举个例子,如果你在我们这个app中选中了Show detail代替了Show,将不会出现导航栏和返回按钮在细节视图中。
- Present modally -这是以模态呈现内容。当我们使用它的时候,细节视图控制器将会从底部以动画的形式升起覆盖全部的iPhone。一个非常好的例子就是我们手机中的日历,当我们点击“+”时就会出现“新建事情”,这就是一个Present modally的样式。
- Present as popover - 它将会把内容显示到一个弹窗上。这种一般见于iPad app上。
现在可以尝试开启模拟器,点击列表行试试效果,你会看见一个空白的页面这表示你已经成功了。你可能会有两个疑问。
- 怎么把信息传到detail view controller中。
- 怎么在detail view controller中显示选中餐厅的图片。
我们会在之后一点点解决这俩个疑问。
我们对界面做些调整,添加一些功能,因为有了这个控制器,所以我们可以删除tableView(:didSelectRowAt:)方法。
在Detail View Controller中创建新的类
选择New File... > Cocoa Touch Class,subclass改为UIViewController。我们必须在新建的类中和视图控制器建立链接。选中view controller并打开Identity inspector。改变它的custom class为刚刚新建的类(比如:RestaurantDetailViewController)。
添加变量到自定义类
我们要做以下这几件事情:
- 创建一个名为restaurantImageName的变量 -当用户在table view controller中选中餐厅时,必须有一种方法将图像名称传递给详细视图。这个变量也将用于数据传递。
- 创建一个outlet名为restauranImageView给图片 - 我们需要一个引用来更新详细视图控制器的图像视图.
好的,接下来我们在RestaurantDetailViewController添加代码:
@IBOutlet var restaurantImageView: UIImageView!
var restauranImage = ""
返回Main.storyboard中,右击Restaurant Detail View Controller对象,拖拽刚刚创建的变量到restaurantImage上。

现在我们已经完成了链接,但是还要做几件事情,我们需要添加图片。 在RestaurantDetailViewController类中的ViewDidLoad方法,添加代码:
override func viewDidLoad() {
super.viewDidLoad()
restaurantImageView.image = UIImage(named: restauranImage)
// Do any additional setup after loading the view.
}
可以自定义添加的图片,我们这里仅仅添加了选中餐厅的图片。
再次编译代码和运行虚拟机,我们会发现还是一片空白。就是说我们还要事情没有完成。其实我们还没有将所选餐厅的图像名称从列表视图控制器传递给详细视图控制器。 这就是之前为什么restaurantmageName变量没有赋值任何值。
通过Segues传输数据
这将是本章关于Segues最为关键的地方。关于Segues的是,Segue管理视图控制器之间的转换,并包含转换中涉及的视图控制器.当触发segue时,在视觉转换发生之前,故事板就运行通知源视图控制器。我们要运用prepare(for:sender)方法。
默认的prepare(for:sender)方法是没有做任何事情的,但是通过重写方法,您可以将任何相关数据传递给新控制器,即我们对象中的Restaurant DetailViewController。
Segues可以由多个源触发。 当故事板变得更复杂时,您很可能在视图控制器之间有多个segue。因此,我们需要给每个Segue添加一个标识符来区分。要为segue分配标识符,要在storyboard editor中,并在Attributes inspector中设置identifier成showRestaurant。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showRestaurant" {
if let indexPath = tableView.indexPathForSelectedRow{
let destinationController = segue.destination as! RestaurantVDetailViewController
destinationController.restauranImage = restaurantImages[indexPath.row]
}
}
}
第一行我们检索标识符,如果标识符相匹配则进行以下代码的操作。在代码行中,首先通过访问tableView.indexPathForSelectedRow来检索所选行.
segue对象包含转换中涉及的源视图控制器和目标视图控制器.其中检索目标控制器我们使用segue.destination。 在我们代码中,目标控制器是RestaurantDetailViewController,所以这也是我通过as!链接它。最后,我们将图像名称传递给目标控制器。
现在你可以再次启动虚拟机,去试试效果。
禁用大标题
在我们点击某一个餐厅,转入这个餐厅的细节视图控制器中,会发现大标题依然存在从而占用了下面的空间。除了在主屏幕中,我们多数不用大标题来吸引人们的眼球。苹果提供给开发者在某个视图控制器中禁用大标题的功能,只需要在ViewDidLoad()方法加入以下代码即可:
navigationItem.largeTitleDisplayMode = .never
结语
本章我们讲了导航和Segues。我们仅仅是简单的完成一个个界面,如果你有想法完全可以自己完善自己的App,做出自己想要的东西。💪