写在开头
很多人说寒哥不写干货 那今天寒哥就狠狠心 写个 (其实不是不写 是太懒了 平时都写在印象笔记中 因为是给自己看的 格式比较散 要写博客 就要认认真真的写 怕误了看官的眼 )
- 顺便来个广告
iOS开发者 群532084214 给大家提供一个交流技术 也可以聊天打屁的平台
此文默认 读者有iOS开发经验 包括OC Swift 和一点点的runtime的理解
先新建个项目 Swift 和oc都行
新建一个OCClass:NSObject
我们来声明一个成员属性


所有人都知道定义这都ivar的时候 系统会帮你做好几件事
生成带下划线的私有成员属性 对应 的setter 和getter
那么我们来Swift中看一下怎么定义一个成员变量

so easy 这个谁不会嘛 (我这里不讨论可选类型 而是讨论 什么叫做存储变量 什么叫做计算变量)
我们会在想 Swift 会不会像oc一样 给我们同样的生成了 setter 和getter呢
于是有的人会这样写

然后这样调用

然后一运行程序 Crash了 很多人 会说 肯定了 不就是循环调用
断点出的堆栈信息 这样的

很明显 这就是循环调用了 但是你把self.去掉 之后再次运行

还是崩
奶奶的要崩溃了 这是什么鬼
其实Swift设计的初衷和oc并不是特别一样
后文解答
我们先来看一个mvc的结构图


其实在mvc中 View是不能拿到model的 他们互相不知道
但是在开发过程中 我们很多view的数据来源自model 如果我们在外部提供一个一个的属性 然后等着控制器 去赋值 再在对应的setter里面去 修改view 的显示 我们会发现很累 因为一个页面可能有太多属性 所以在大多数情况 我们在view声明一个model的属性 等值控制器去赋值
但是
但是
但是
重要的事情说三遍
我们这样我违反了 mvc的思想 其实(mvvm)也是这样的 view不能拿到model 因为你拿到了model 就可以修改 就会造成页面中的数据不对应
大风险啊
于是Swift中出现了 计算变量这种东西
- 什么叫计算变量 还有什么叫存储变量 ?
什么鬼
我们声明了一种变量就是为了存储数据 但是Swift中有一种特殊的变量 叫做 计算变量 这种变量是 不能存放数据 (你特么又在逗我 )
看官 我真的没逗你 是真的 这种变量主要就是为了 在view里面声明一个只读的变量 去来给页面赋值的 例子

这种办法就巧妙的 避开了以前在OC开发iOS时 可能对mvc造成的规则不符的情况
- 这里出现了其他的情况 就是我真的想拥有一个变量 还想在setter方法里面做些别的操作
这里我们出现了先入为主的观念 很多java C++ 和OC开发者 都以为对于的setter就是对应的Set方法 其实不是这样的额
在Swift中访问控制是有访问控制关键字来决定的
如

对于的监听方法就变成了这样

在早期 apple 建议开发者 都使用 view 使用kvo去观察model的变化 来给对于的页面赋值 但是也不知道程序员的习惯 还是如何 大家还是我行我素 就在view中拿到model
在Swift中 建议使用计算变量 来给view赋值
- 关于网上对于计算变量的写法

很多人 都模仿 OC中的写法 自己写个带下划线的私有变量 然后提供 set和get方法 我只能说你根本就没有理解Swift 带着陈旧的思想去学习 多此一举嘛
- 关于两个问题
-
我真的想在计算属性里面存值
-
属性观察期的位置 固定了 那以前的kvo怎么办
还记得OC中的面试题吗
category 声明一个property 是什么意思
怎么给category增加成员属性
在oc的category中写了一个property 其实系统帮你做了一个对应的set 和 get方法的声明 具体也不会有私有变量生成 也不会有方法实现 如果你真的要加变量 就要用到kvo的 关联对象 如果你对runtime不熟悉 去简述搜 runtime 很多好文章


在Swift中是这样的

关于kvo Swift的初衷就是为了创造几门极度安全化的语言 所以Swift不建议我们再 使用kvo了 因为 在oc中kvo 会产生 一个私有的中间类 (不懂去看runtime ) 在Swift 真的想用kvo 就要用黑魔法了
参看自喵神的tips




“在 Swift 中使用 KVO 有两个显而易见的问题。
首先是 Swift 的 KVO 需要依赖的东西比原来多。在 Objective-C 中我们几乎可以没有限制地对所有满足 KVC 的属性进行监听,而现在我们需要属性有 dynamic 进行修饰。大多数情况下,我们想要观察的类不一定是 dynamic 修饰的 (除非这个类的开发者有意为之,否则一般也不会有人愿意多花功夫在属性前加上 dynamic,因为这毕竟要损失一部分性能),并且有时候我们很可能也无法修改想要观察的类的源码。遇到这样的情况的话,一个可能可行的方案是继承这个类并且将需”“要观察的属性使用 dynamic 进行重写。比如刚才我们的 MyClass 中如果 date 没有 dynamic 的话,我们可能就需要一个新的 MyChildClass 了:”
最后再来个广告 受到 公众号主人邀请 我的文章也会被发布到这个公众号
** 加个欢迎微信扫码关注吧**

网友评论