学习理论知识是非常重要的,昨天面试swift,自以为用swift写了小项目就会了,结果面试的时候是啪啪打脸,尴尬到死,自己都能从面试官眼中看到自己的窘迫,奇耻大辱啊!各种特性都没有了解清楚就轻易去面试swift无异于自取其辱。从今天开始总结swift的特性以及相关知识点,做到知其然知其所以然,再也不要再重复昨天的错误了。
一、值类型&引用类型
- 值类型
直接将内存存储在栈内,由系统自动释放资源的数据类型,称之为值类型,致列行每个实例都保持一份数据拷贝。
包含: Int, Double,Float,String,Array,Dictionary,Set 其实都是用结构体实现的,也是值类型。
内存存储在堆区域。引用类型的赋值是浅拷贝,即新对象和源对象引用的内存地址是相同的。
包含对象(Object),类,接口,委托。
二、stack & heap
- 内存(RAM)中有两个区域,栈区(stack)和堆区(heap)。
- 在 Swift 中,值类型,存放在栈区;引用类型,存放在堆区。
- 堆是先进先出,而栈是先进后出。
三、类和结构体
一个类的实例被称为对象。然而,swift中类和结构体比其它任何一门语言都接近。
相同点:
1.定义属性用于存储值。
2.定义函数以提供功能
3.定义下标,以便用下标语法来访问它们的值。
4.定义初始化程序,以创建它们的初始状态。
5.通过扩展来扩展它们的默认实现。
6.利用协议来完成特定标准功能。
类比结构体多的功能:
1.类可以继承,使子类具有父类的功能。
2.类型转换允许你在运行时,检查和解释一个类实例的类型。
3.取消初始化器,允许一个类的实例释放它所占有的资源。
4.计数器允许对一个实例进行多次引用。
* 结构体在代码传递的时候不是进行引用,而总是被拷贝。类是被引用的。
苹果推荐使用struct,原因在于它在小数据模型传递和拷贝时比 class 要更安全,在多线程和网络请求时尤其好用
class A {
var val = 1
}
var a = A()
var b = a
b.val = 2
此时 a 的 val 也被改成了 2,因为 a 和 b 都是引用类型,本质上它们指向同一内存。改变了源数据是很不安全的。解决办法就是使用struct。
struct A {
var val = 1
}
var a = A()
var b = a
b.val = 2
此时,a,b互不影响,因为他们是两块不同的内存。
类和结构体的命名
两者都要用首字母大写的驼峰命名法。相反,命名属性和方法要要用首字母小写的矮驼峰来和类型进行区分。
结构体都有一个自动生成的初始化器,它可以用来初始化新结构体的属性。不像结构体,类没有这种默认的初始化器
四、Swift 到底是面向对象还是函数式的编程语言?
- 首先,swift既是面向对象又是函数式编程语言.
- 面向对象语言:swift支持类的封装继承和多态,这是面向对象的三大特征。
- 函数式编程语言:swift支持map, reduce, filter, flatmap这类去除中间状态、数学函数式的方法,更加强调运算结果而不是中间过程。
1、map:可以对数组中的每一个元素做一次处理
2、flatMap与map不同之处:
(1)flatMap返回后的数组中不存在nil,同时它会把Optional解包。
(2)flatMap还能把数组中存有数组的数组(二维数组、N维数组)一同打开变成一个新的数组。
(3)flatMap也能把两个不同的数组合并成一个数组,这个合并的数组元素个数是前面两个数组元素个数的乘积。
3、filter 可以取出数组中符合条件的元素 重新组成一个新的数组
let numbers = [1,2,3,4,5,6]
let evens = numbers.filter { $0 % 2 == 0 }
// [2, 4, 6]
print(evens)
4、reduce:计算,可以对数组的元素进行计算
知识传送门1
知识传送门2
六、Optional Type&Normal Type
我们可以把类型分为普通类型(Normal Type)(例如, String, Array …)和可选类型(Optional Type)。
swift中使用普通类型表示值一定存在,用可选类型(Optional Type)来表示其所对应的值可能存在可能为nil。
Optional Type 的本质是一个枚举类型,它枚举的是None(nil)和NormalType,如下所示:
enum Optional {
case None
case Normal(T)
}
所以其实OptionalType和NormalType是一个包含关系。
我们在写代码的时候也会发现,对于一个要传入NormalType的函数,如果传入一个有枚举情况的Optional的值是会报错的:
open func appending(_aString:String) ->String
var stringA : String = "a"
let stringB : String? = "b"
stringA.appending(stringB) // 编译错啦
普通的可选类型用 ‘?’ 来声明,表示该值可能存在可能为nil。相当于声明了一个包含 Optional.None和Optional.Some(T)的枚举类型。
隐式拆包用 ‘!’ 来声明,表示确认该值不为nil,一定存在。相当于声明了Optional.Some(T)。