swift从入门到精通18-访问控制和内存管理

278 阅读2分钟

1.访问控制

  • open:允许在定义实体的模块、其他模块中访问,允许其他模块进行继承、重写
  • public:允许在定义实体的模块、其他模块中访问,不允许其他模块进行继承、重写 
  • internal:只允许在定义实体的模块中访问,不允许在其他模块中访问 
  • fileprivate:只允许在定义实体的源文件中访问
  • private:只允许在定义实体的封闭声明中访问 

2.使用准则

一个实体不可以被更低访问级别的实体定义。一般情况下,类型为private或fileprivate,那么成员\嵌套类型默认也是private或fileprivate ,类型为internal或public,那么成员\嵌套类型默认是internal。

3.内存管理

OC一样,Swift也是采取基于引用计数的ARC内存管理。

Swift的ARC中有3种引用:

  1. strong ,强引用,默认也是强引用。
  2. weak ,弱引用,必须是可选类型的var,因为实例销毁后,ARC会自动将弱引用设置为nil
  3. unowned ,无主引用,不会产生强引用,实例销毁后仍然存储着实例的内存地址。

4.weak和unowned限制

只能使用在类实例上面

class Person {}
weak var p: Person?
unowned var p1: Person?

5.循环引用

weak、unowned 都能解决循环引用的问题,unowned 要比weak 少一些性能消耗。

在生命周期中可能会变为 nil 的使用 weak。

初始化赋值后再也不会变为 nil 的使用 unowned。

6.闭包的循环引用

可以lazy属性是闭包的调用的结果,则不用考虑循环引用问题。

class Person {
    var age: Int = 0
    lazy var getAge: Int = {
        self.age
    }()
    deinit { print("deinit") }
}

7.逃逸闭包

非逃逸闭包、逃逸闭包,一般都是当做参数传递给函数。

非逃逸闭包:闭包调用发生在函数结束前,闭包调用在函数作用域内。

逃逸闭包:闭包有可能在函数结束后调用,闭包调用逃离了函数的作用域,需要通过@escaping声明。

typealias Fn = () -> ()
func test1(_ fn: Fn) {
    fn()
}

var gFn: Fn?
func test2(_ fn: @escaping Fn){
    gFn = fn
}

8.内存访问冲突

内存访问冲突会在两个访问满足下列条件时发生: 

  •  至少一个是写入操作
  • 它们访问的是同一块内存
  • 它们的访问时间重叠(比如在同一个函数内)

例子:

//不存在冲突
func plus(_ num: inout Int) -> Int {
    num + 1
}


var number = 1
number = plus(&number)


//存在访问冲突
func plus1(_ num: inout Int){
    return num += number
}


plus1(&number)


//解决冲突
var otherNumber = number
plus1(&otherNumber)
number = otherNumber


上一篇文章:swift从入门到精通17-拓展

下一篇文章:swift从入门到精通19-字面量