干货之前:补充一下可选链(optional chain)

 class A {
var p: B? } class B
{
var p: C?
} class C {
func cm() -> String {
print("cm")
return "abc"
}
} let insa = A()
let insb = B()
let insc = C()
insa.p = insb
//insa.p = nil
insb.p = insc let r = insa.p?.p?.cm()

解析:此处定义了A,B,C三个类,使其依次关联,最后通过类A实例的属性拿到B实例,依次拿到C实例再调用C的方法。

注意:1,中间任何一个地方为nil,不报错,但导致整个结果为nil。

2,如果没有一个地方为nil,整个表达式才正常执行。

内存管理

swift中的或者java,c#语言的内存管理,指的就是引用类型对象的管理,也就是对“堆(heap)”里面的对象的管理。

这三种语言中,值类型不需要进行内存管理,值类型是放在栈里的,程序会自动管理,不需要特别的机制。

swift中的内存管理技术,叫做arc,自动引用计数(Auto Reference Count) 当对对象的引用计数为0时,立即销毁对象

这种管理一般会产生两种错误可能

1.空引用

2.内存泄露(leak) 某个时候,某些对象分配了内存,但因为某些原因,导致程序结束时,此对象所占的内存没有被回收

我们可以控制的引用计数的数量 增加的方法 1.声明变量,指向某个对象(直接new或者把别的变量的值赋值给你 )

减少的方法

1.f = nil(表示不指向任何东西)

2.变量一般会运行在函数中,变量本身是存放在栈中的 所以函数结束时,此变量消失

关于循环引用swift提供了两种方法来解决,

一种是weak(弱),一种是unowned(未拥有)

1.weak 可以修饰在可为空(?,!)的属性上

2.unowned只能修饰在非可为空的属性上。

循环引用案例

 class A {
var p: B?
init() {
print("a********************")
}
deinit {
print("a--------------------")
}
} class B{
var p: A?
init() {
print("b********************")
}
deinit {
print("b--------------------")
} }
var f1:A? = A()
var f2:B? = B()
//使用这两个类时,可以从控制台看到这两个类已经初始化完毕
//通过f1f2两个对象的属性将这两个类相互关联
f1?.p = f2
f2?.p = f1
//此时再将这两个对象赋值为nil
//f1 = nil
//f2 = nil
//但此时并没有调用类的析构函数
//原因:f1f2这两个对象的属性相互引用了这两个对象
f1?.p = nil
f2?.p = nil
f1 = nil
f2 = nil

解析:1,此处现将f1f2两对象的属性赋值为nil再将f1f2赋值为nil即代表A,B这两个类完全没有引用,此时才会调用析构函数,回收内存。

2,以上这种循环引用的问题,对象并没有真正清除常常会导致内存泄漏(leak)

解决方法一:weak

 class C {
var p: D?
init() {
print("c********************")
}
deinit {
print("c--------------------")
}
} class D{
weak var p: C?
init() {
print("d********************")
}
deinit {
print("d--------------------")
} }
var f3:C? = C()
var f4:D? = D()
f3 = nil
f4 = nil

此时发现在任何一个循环引用的属性上加上weak关键字,即可解决上述问题

注意:weak 可以修饰在可为空(?,!)的属性上

解决方式二:unowned

 class E {
var p: F?
init() {
print("e********************")
}
deinit {
print("e--------------------")
}
} class F{
unowned var p: E
init(a:E) {
p = a
print("f********************")
}
deinit {
print("f--------------------")
} }
var f5:E? = E()
var f6:F? = F(a:f5!)
f5 = nil
f6 = nil

注意:unowned只能修饰在非可为空的属性上。




Swift中的可选链与内存管理(干货系列)的更多相关文章

  1. C++中的垃圾回收和内存管理

    最开始的时候看到了许式伟的内存管理变革系列,看到性能测试结果的时候,觉得这个实现很不错,没有深入研究其实现.现在想把这个用到自己的一个项目中来,在linux下编译存在一些问题,所以打算深入研究一下. ...

  2. swift中的可选类型

    可选类型也是Swift语言新添加的对象.主要是为了解决对象变量或常量为空的情况.在前面定义的变量和常量都不能为空.里面必须要有值. Swift中的可选类型则允许变量(常量)中没有值(被设为nil).要 ...

  3. swift 学习- 19 -- 可选链式调用

    // 可选链式调用 是一种在当前值可能为 nil 的可选值上请求 和 调用属性, 方法以及下标, 如果 可选值有值, 那么调用就会成功, 如果可选值是 nil, 那么就会将返回 nil , // 多个 ...

  4. 高端内存映射之vmalloc分配内存中不连续的页--Linux内存管理(十九)

    1 内存中不连续的页的分配 根据上文的讲述, 我们知道物理上连续的映射对内核是最好的, 但并不总能成功地使用. 在分配一大块内存时, 可能竭尽全力也无法找到连续的内存块. 在用户空间中这不是问题,因为 ...

  5. Swift 值类型和引用类型的内存管理

    1.内存分配 1.1 值类型的内存分配 在 Swift 中定长的值类型都是保存在栈上的,操作时不会涉及堆上的内存.变长的值类型(字符串.集合类型是可变长度的值类型)会分配堆内存. 这相当于一个 &qu ...

  6. Java中的垃圾回收机制&内存管理&内存泄漏

    1. Java在创建对象时,会自动分配内存,并当该对象引用不存在的时候,释放这块内存. 为什么呢? 因为Java中使用被称为垃圾收集器的技术来监视Java程序的运行,当对象不再使用时,就自动释放对象所 ...

  7. Swift中的可选协议和方法的历史渊源

    @objc protocol Transaction { func commit() -> Bool optional func isComplete() -> Bool } 以上协议被标 ...

  8. 使用Boost库中的组件进行C++内存管理

    C++标准库中的auto_ptr,智能指针,部分的解决了获取资源自动释放的问题 在Boost中,提供了6中智能指针:scoped_ptr, scoped_array, shared_ptr, shar ...

  9. C++中的垃圾回收和内存管理(续)

    boost memory的gc_allocator的使用 首先编译生成boost-memory的库,由于生成的是.so的动态库,所以需要在运行程序之前,将库文件的路径添加到LD_LIBRARY_PAT ...

随机推荐

  1. appfuse:Excel导出

    1.pom.xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi< ...

  2. JAVA NIO Buffer

    所谓的输入,输出,就是把数据移除或移入缓冲区.   硬件不能直接访问用户控件(JVM). 基于存储的硬件设备操控的是固定大小的数据块儿,用户请求的是任意大小的或非对齐的数据块儿.   虚拟内存:使用虚 ...

  3. 数据库实战案例—————记一次TempDB暴增的问题排查

    前言 很多时候数据库的TempDB.日志等文件的暴增可能导致磁盘空间被占满,如果日常配置不到位,往往会导致数据库故障,业务被迫中断. 这种文件暴增很难排查,经验不足的一些运维人员可能更是无法排查具体原 ...

  4. 严重: Exception loading sessions from persistent storage Java.io.EOFException

    tomcat启动时报此异常,但web页均能正常运行:对程序影响不大. /*具体原因时tomcat--work--(你当前运行的工程名)--session.ser*/删除即可解决 分析: EOFExce ...

  5. 《InsideUE4》UObject(二)类型系统概述

    曾子曰:吾日三省吾身--为人谋而不忠乎?与朋友交而不信乎?传不习乎? 引言 上一篇我们谈到了在游戏引擎,或者在程序和高级编程语言中,设计一个统一对象模型得到的好处,和要付出的代价,以及在UE里是怎么对 ...

  6. Java动态代理

    代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关 ...

  7. [No00008F]PLSQL自动登录,记住用户名密码&日常使用技巧

    配置启动时的登录用户名和密码 这是个有争议的功能,因为记住密码会给带来数据安全的问题. 但假如是开发用的库,密码甚至可以和用户名相同,每次输入密码实在没什么意义,可以考虑让PLSQL Develope ...

  8. [LeetCode] Power of Four 判断4的次方数

    Given an integer (signed 32 bits), write a function to check whether it is a power of 4. Example: Gi ...

  9. [LeetCode] Min Stack 最小栈

    Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...

  10. 如何在ASP.NET Core中实现CORS跨域

    注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...