写在开头 iOS开发者 群173499350 给大家提供一个交流技术 也可以聊天打屁的平台
翻译自Swift官方Blog
- 我们在用swift设计开发时的一个重点就是 如何提高编码模型的内存安全问题 本文讲解了一个内存安全的问题 :
如何确保变量有一个初始值才能使用。
- swift版简介
变量什么时候是安全的 ? 开发者认为无论任何时候访问一个变量时 都有一个值 而不是
nil
像其他编程语言 比如C 要求程序员对内存模型的编程技术非常严格 但是这是有风险的 人总会犯错C++
和OC
用了其他方式改善这种可能造成错误的地方 如OC[nil message]
会被忽视 有的语言要求更严格 不赋值 就无法编译
目前解决这种办法采用的技术是让编译器执行数据流分析 如果变量不初始化无法编译通过 像java
C#
都采用这种技术 Definitive Initialization
注意Swift不仅仅使用这一项技术
-
初始化一个局部变量
类型推断允许你这样写var myInstance : MyClass // 定义一个非可选的局部变量 if x > 42 { myInstance = MyClass(intValue: 13) } else { myInstance = MyClass(floatValue: 92.3) } // myInstance已经初始化 所以在下面可以使用 myInstance.printIt()
这里很简单的可以确定变量已经初始化 可以保证不会访问那些未初始化的内存 避免Crash 但是有时候流程可能更加复杂
var myInstance : MyClass
if x > 10 {
myInstance = MyClass(intValue: 13)
}
// ...其他操作
if x > 42 {
myInstance.printIt()
}
这时编译器可能告诉你 “Variable myInstance used before initialized” on the call to printIt()
其实就是说变量未初始化 编译器不可能做所有预测 或者类型推断 这就要求我们不要写这么复杂的逻辑 去初始化一个变量
在普通数据类型如int 初始化时可以直接这样
var index = 0
但是其他情况可能就要用到init()
- 其他技术补充
鉴于C语言的兼容性 有时候我们需要使用一些C不安全的API 如
UnsafePointer
这样的代码会造成程序运行时Crash 这就要求程序员永远不犯错
- 隐式初始化
有些编程语言会有一些默认值 比如声明一个变量 int a未给这个变量赋值的情况下 我们就给一个默认值 r如0 但是Swift 没有采用这种考虑 原因如下
如果有些Protocol没有要求实现init()方法 这样一个变量就可能引用一个未初始化的对象 遗留在Cocoa编程中 这种情况太常见了
就算不给变量默认值 自己写一个也并不麻烦 而且会提前发现很多错误 使代码更容易维护
注意 只有可选类型或者隐式可选默认值才是nil
所以Swift采用了 访问一个变量前必须初始化