美文网首页
CS193笔记 第六讲 多重MVC,控制器的生命周期和内存管理

CS193笔记 第六讲 多重MVC,控制器的生命周期和内存管理

作者: 默默熊 | 来源:发表于2017-03-23 11:16 被阅读17次

我开始用Markdown方式来记笔记了。现在第十一讲的视频都已经放出来了。为了提速,内容会记得比较简单,以记录核心内容为主,后面再逐步进行补充。对本讲有任何疑问,请留言,我会优先进行更新。

<h4>本讲简介:</h4> 本讲通过演示来介绍,最后几分钟时间介绍了内存管理,主要是对引用类型对象的管理。

演示:
为FaceIt增加 Master-Detail View

Navigation View

View Controller 的生命周期

Instantiated
awakeFromNib
segue preparation happens
outlets get set
viewDidLoad
viewWillAppear
viewWillLayoutSubviews
viewDidLayoutSubviews
viewWillDisappear

内存管理
简单来讲,内存管理是自动的或对开发者透明的。

ARC vs MRC vs GC
自动引用计数
手动引用计数
垃圾回收技术

Strong Weak unOwned

闭包 (Closures)

Closures: 一等公民,是引用类型,居住在堆上
<pre>addUnaryOperation("✅", operation: { (x: Double) -> Double in
display.textColor = UIColor.green
return sqrt(x)
} )</pre>

<pre>addUnaryOperation("✅") {
self.display.textColor = UIColor.green
return sqrt($0)
} </pre>

<pre>addUnaryOperation("✅") { [ unowned me = self ] in
me.display.textColor = UIColor.green
return sqrt($0)
} </pre>

这个例子有几个知识点:
1,闭包做为最后一个参数的简化写法
2,介绍了一种可能产生内存引用互锁的情况
3,引入一个unowned 变量 打破循环

更容易想到的打破循环引用的
<pre>addUnaryOperation("✅") { [ weak weakSelf = self ] in
weakSelf?.display.textColor = UIColor.green
return sqrt($0)
} </pre>

但还可以这样写

<pre>
addUnaryOperation("✅") { [ weak self ] in
self?.display.textColor = UIColor.green
return sqrt($0)
}
</pre>

第十三讲结尾介绍了一个需要避免memory cycle 的情况

@escaping 用于修饰闭包。闭包默认是非逃逸的。@escaping修饰表示逃逸,即闭包的执行会产生对闭包外部的访问,或某种形式上的副效果。在Swift 3以前,闭包默认是逃逸的, 非逃逸闭包要用@noescaping修饰。

<h4>再谈!</h4>
上一讲里面提到过,因为在声明faceView时使用了!,在使用它时是不需要加?的。但在本讲中,如果在下面访问faceView时不加?,应用会出错。

<pre>
//FaceViewController.swift
@IBOutlet weak var faceView: FaceView!

private func updateUI() {
    switch  expression.eyes {
    case .open:
        faceView?.eyesOpen = true
    case .closed:
        faceView?.eyesOpen = false
    case .squinting:
       faceView?.eyesOpen = false
    }
    faceView?.mouthCurvature = mouthCurvature[expression.mouth] ?? 0.0
}</ol>

</pre>

原因在于,Segue总会建立新的MVC实例。而在 prepare(for segue) 中<code> faceViewController.expression = expression </code>引发了对上面的updateUI()的调用,而此时faceView还没有被建立,仍然为nil。所以需要加?。这说明使用!后,只是对编译器来说可以接受没有unwrapping。但像本例的情况仍然需要。

<pre>
<ol> //EmotionsViewController.swift
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationViewController = segue.destination
if let faceViewController = destinationViewController as? FaceViewController,
let identifier = segue.identifier,
let expression = emotionalFaces[identifier] {
faceViewController.expression = expression
}
}<ol>
</pre>

<h4>课后练习</h4>
<p>在增加了navigation Controller 后,应用启动后直接显示了 Face View。老师留了一个练习,是希望启动后显示带有三个按钮的emotion 选择页面。老师还给了个提示,要用到后面讲的delegate的内容。在这儿我们自己实现一下。</p>
<ol><li>打开帮助文档,在输入框敲入 Navig,这时提示列表就回显示出一些推荐的结果,选取 navigationController(_:willShow:animated:)
<li>根据帮助内容我们确定这个方法会在每一页显示前被调用。而且从帮助页面的顶部我们可以知道这个方法属于协议 UINavigationControllerDelegate
<li>创建一个新的 Cocoa Touch Class 文件,将其命名为EmotionsNavViewController,父类先不用动,后面再改。
<li>打开Main.storyboard, 选中Navigation Controller 查看 identity inspector 中的 class 为 UINavigationController。因而我们打开新建的文件,将
<pre><code>class EmotionsNavViewController: ... { </code></pre> 替换为
<pre><code>class EmotionsNavViewController: UINavigationController, UINavigationControllerDelegate {</code></pre>回到 identity inspector 中将Navigation Controller 的 class 的值改为 EmotionsNavViewController
<li>在类中添加我们在第1步找到的方法
<pre> func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
}</pre><li>在这儿我们该怎么做呢?查看UINavigationController的帮助
“A navigation controller coordinates its behavior with its delegate object. The delegate object can override the pushing or popping of a view controller ... "
我们看到了 override,所以有戏。我们在willShow 方法中加入
<pre><code>popViewController(animated: true)</code></pre>运行一下,没有效果。在新加的代码上设一个断点,会发现根本没有被调用。
<li>在viewDidLoad()里面加入
<pre><code>delegate = self</code></pre>再次执行程序,成功地显示了我们想要的页面。
<li>点一下 sad 按钮,oops! FaceView 出现后又收回了。看来willShow中的代码还在起作用。增加一个属性
<pre>private var displayed = false</pre>然后将 willShow的内容改为
<pre>if displayed == false {
displayed = true
popViewController(animated: true)
}</pre> command+R 运行程序。一切OK。</ol>

官方答案在第八讲。

相关文章

  • CS193笔记 第六讲 多重MVC,控制器的生命周期和内存管理

    我开始用Markdown方式来记笔记了。现在第十一讲的视频都已经放出来了。为了提速,内容会记得比较简单,以记录核心...

  • Swift学习笔记Day0725

    写一写笔记,记录自己的学习,就这样~ 控制器的生命周期: 指的是MVC中控制器的生命周期,以及在其生命周期的各个阶...

  • [iOS] MVC 中的 UIViewController 定

    对于 MVC 中 C 控制器基本的理解是 管理视图, 控制其生命周期 联系模型和视图 此外还做的工作有: 管理控制...

  • CS193笔记 第五讲 手势和多重MVC

    本讲简介:本讲分为两部分。首先是为上一讲的FaceIt增加了Model和三种手势操作。然后对多重MVC,以及iOS...

  • UIViewController

    UIViewController职责视图管理处理与视图相关的通知实现容器视图控制器内存管理生命周期 UIViewC...

  • iOS文档补完计划--UIViewController

    目录 UIViewController职责视图管理处理与视图相关的通知实现容器视图控制器内存管理生命周期 以代码的...

  • iOS - 架构模式(Design Pattern)

    MVC Cocoa 的 MVC 模式驱使人们写出臃肿的视图控制器,因为它们经常被混杂到 View 的生命周期中,因...

  • ios中常用的开发模式

    1、MVC模式 ---------> 模型-视图-控制器 Model(模型): 1)管理App的数据和状态...

  • Glide内存管理

    1.前言 Glide框架的核心内容主要包含生命周期自动管理和内存管理,生命周期管理在《Glide源码分析-生命周期...

  • Android Jetpack - ViewModel

    ViewModel 简述 ViewModel 旨在以生命周期感知的形式存储和管理 UI 控制器(Activity/...

网友评论

      本文标题:CS193笔记 第六讲 多重MVC,控制器的生命周期和内存管理

      本文链接:https://www.haomeiwen.com/subject/hunwnttx.html