威立山

记录心路历程

0%

Value and Reference Type

Swift中值类型和引用类型

本文主要介绍值类型、以及使用Struct作为数据模型的注意事项

值类型(value type)

值类型:每次分配给变量/常量或者作为参数传递到函数时,都会重新创建(复制)一个新的实例。

Swift 中的所有的内建类型都是值类型,不仅包括了传统意义像 Int,Double这些,甚至连 String,Array 以及 Dictionary 都是值类型的(与OC不同), swift中所有的Struct 和 enum 都是值类型,值类型每次初始化以后,将它分配或者传递时,实际上是分配或传递了它的一个拷贝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Point {
var x : Int
var y : Int
init(x:Int, y:Int) {
self.x = x
self.y = y
}
}

var aPoint = Point(x: 10, y: 10)
var bPoint = aPoint
bPoint.x = 5
print(aPoint)
print(bPoint)

打印结果

Point(x: 10, y: 10)

Point(x: 5, y: 10)

总结

  1. 赋值给新变量,会产生一个单独的、没有数据共享的新实例.
  2. 值类型在复制时,会将存储在其中的值类型一并进行复制,而对于其中的引用类型的话,则只复制一份引用。
  3. 复制时机,是在值类型中的内容发生改变时!值类型每次复制会增加额外开销,Swift将这种开销控制在最小的范围内,在没有必要复制时,复制是不会发生的。(≧▽≦)/

线程安全:
在Swift中,Array、String、Dictionary都是值类型。它们的使用方式类似C语言中得int,每一个实例都有一份数据。你不需要进行显示的复制操作去防止数据在你不知情的情况下被修改。更重要的是,你可以跨线程进行传参而不需要考虑同步的问题,因为传递值类型很安全。(Swift官方博客

引用类型(Reference Types)

引用类型:引用类型初始化后,无论是分配给变量还是常量,或是通过参数传递给函数,都将是同一个实例对象。
NSObject再熟悉不过了,当在分配或传递是都是引用,都指向那个原始对象。不再多说了~

Struct数据模型

处理数据结构时有时会用Struct进行处理,使用 Struct 来代替 Class 作为数据模型有很多好处。值类型是非常有优势的:

  • 安全性 :因为 Struct 是用值类型传递的,它们没有引用计数。
  • 内存:由于他们没有引用数,他们不会因为循环引用导致内存泄漏。
  • 速度:值类型通常来说是以栈的形式分配的,而不是用堆。因此他们比 Class 要快很多,真的很多!在 StackOverflow 给 Struct 和 Class 进行相同操作的表现做了基准测试,Struct 比 Class 要快九百倍。
  • 拷贝:在 Objective-C 里拷贝一个对象,你必须选用正确的拷贝类型(深拷贝、浅拷贝),这是非常烦人的,值类型的拷贝则非常轻松!
  • 线程安全:值类型是自动线程安全的。无论你从哪个线程去访问你的 Struct ,都非常简单。

Struct的缺点:

  • OC无法调用Swift的Struct,当你的项目的代码是 Swift 和 Objective-C 混合开发时,你会发现在 Objective-C 的代码里无法调用 Swift 的 Struct。因为要在 Objective-C 里调用 Swift 代码的话,对象需要继承于 NSObject。
  • 不能继承,继承是面向对象编程的四大特性之一,没有继承就不能抽象一个统一模型
  • Struct 不能被序列化成 NSData 对象。某些时候会把数据存在 NSUserDefaults 里,而Struct 转化成NSData,技术可行但坑多

参考:

王巍Swift Tips

SwiftGG