经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Swift » 查看文章
Swift?列举内存管理与异常处理具体代码
来源:jb51  时间:2021/11/24 12:48:14  对本文有异议

1. Swift 内存销毁时机

  1. // Swift5 内存销毁时机
  2. // 引用类型的内存销毁时机
  3. class ClassDemo {
  4. var a = "value a"
  5. deinit {
  6. // 实例被释放
  7. print("deinit class a")
  8. }
  9. }
  10.  
  11. // 可空类型
  12. var ins1: ClassDemo? = ClassDemo()
  13. var ins2 = ins1
  14. var ins3 = ins2
  15.  
  16. ins1 = nil // 取消 ins1 引用
  17. ins2 = nil // 取消 ins2 引用
  18. print(String(describing: ins3?.a)) // 此处 ins3 引用的实例依然在,Optional("value a")
  19.  
  20. // 对实例引用被全部取消,ClassA 实例此处才销毁
  21. ins3 = nil // deinit class a
  22.  

2. Swift 单向引用

  1. // Swift5 单向引用
  2. class ClassA {
  3. deinit {
  4. print("deinit ClassA")
  5. }
  6. func foo() {
  7. print("func foo in ClassA")
  8. }
  9. }
  10.  
  11. class ClassB {
  12. // 此处引用 ClassA 的实例
  13. var ins: ClassA?
  14. init(ins: ClassA?) {
  15. self.ins = ins
  16. }
  17. deinit {
  18. print("deinit ClassB")
  19. }
  20. }
  21.  
  22. var clzA: ClassA? = ClassA()
  23. var clzB: ClassB? = ClassB(ins: clzA)
  24.  
  25. // 此处 clzA 所引用的内存并未释放
  26. clzA = nil
  27. // 依然可以调用 clzB 中的 clzA 实例的 foo 方法
  28. clzB?.ins?.foo() // func foo in ClassA
  29. // 此时 ClassB 实例被释放,不再有引用指向 ClassA 随即所占内存也被释放
  30. clzB = nil // deinit ClassB \n deinit ClassA
  31.  

3. Swift 循环引用

  1. // Swift5 循环引用
  2. class ClassC {
  3. var insD: ClassD?
  4. deinit {
  5. print("deinit ClassC")
  6. }
  7. func foo() {
  8. print("func foo in ClassC")
  9. }
  10. }
  11.  
  12. class ClassD {
  13. // 此处引用 ClassC 的实例
  14. var insC: ClassC?
  15. init(ins: ClassC?) {
  16. self.insC = ins
  17. }
  18. deinit {
  19. print("deinit ClassD")
  20. }
  21. }
  22.  
  23. var clzC: ClassC? = ClassC()
  24. var clzD: ClassD? = ClassD(ins: clzC)
  25.  
  26. clzC?.insD = clzD
  27.  
  28. // 此处 clzC 所引用的内存并未释放,对应实例被 clzD 的 insC 引用
  29. clzC = nil
  30. // 依然可以调用 clzD 中的 insC 实例的 foo 方法
  31. clzD?.insC?.foo() // func foo in ClassC
  32. // 此时 clzD 的实例依然被 clzC 的 insD 引用,clzC 和 clzD 实例都未被释放
  33. clzD = nil
  34.  

4. Swift 弱引用 解决 循环引用 问题

  1. // Swift5 使用 弱引用 解决 循环引用
  2. class ClassE {
  3. // 弱引用 weak
  4. weak var insF: ClassF?
  5. deinit {
  6. print("deinit ClassE")
  7. }
  8. func foo() {
  9. print("func foo in ClassE")
  10. }
  11. }
  12.  
  13. class ClassF {
  14. // 此处引用 ClassE 的实例
  15. var insE: ClassE?
  16. init(ins: ClassE?) {
  17. self.insE = ins
  18. }
  19. deinit {
  20. print("deinit ClassF")
  21. }
  22. }
  23.  
  24. var clzE: ClassE? = ClassE()
  25. var clzF: ClassF? = ClassF(ins: clzE)
  26.  
  27. clzE?.insF = clzF
  28.  
  29. // 此处 clzE 所引用的内存并未释放,对应实例被 clzF 的 insE 引用
  30. clzE = nil
  31. // 依然可以调用 clzF 中的 insE 实例的 foo 方法
  32. clzF?.insE?.foo() // func foo in ClassE
  33. // 此时 clzF 的实例被 clzE 的 insF 弱引用,会被销毁,clzE 和 clzF 实例都能被释放
  34. clzF = nil // deinit ClassF \n deinit ClassE
  35.  

5. Swift 无主引用,针对类型为非 Optional

  1. // Swift5 无主引用,针对类型为非 Optional
  2. class ClassG {
  3. // 无主引用 unowned 假定属性不为 nil
  4. unowned var insH: ClassH
  5. init(ins: ClassH) {
  6. self.insH = ins
  7. }
  8. func foo() {
  9. print("func foo in ClassG")
  10. }
  11. deinit {
  12. print("deinit ClassG")
  13. }
  14. }
  15.  
  16. class ClassH {
  17. // 此处引用 ClassE 的实例
  18. var insG: ClassG?
  19. deinit {
  20. print("deinit ClassH")
  21. }
  22.  
  23. }
  24. var clzH: ClassH? = ClassH()
  25. var clzG: ClassG? = ClassG(ins: clzH!)
  26.  
  27.  
  28. clzH?.insG = clzG
  29.  
  30. // 此处 clzG 所引用的内存并未释放,对应实例被 clzH 的 insG 引用
  31. clzG = nil
  32. // 依然可以调用 clzH 中的 insG 实例的 foo 方法
  33. clzH?.insG?.foo() // func foo in ClassG
  34. // 此时 clzH 的实例被 clzG 的 insH 无主引用,会被销毁,clzG 和 clzH 实例都能被释放
  35. clzH = nil // deinit ClassH \n deinit ClassG
  36.  

6. Swift 闭包产生的循环引用

  1. // Swift5 闭包产生的循环引用
  2. class ClassJ {
  3. var field = "field j"
  4. lazy var closure: () -> Void = {
  5. print(self.field)
  6. }
  7. deinit {
  8. print("deinit ClassJ")
  9. }
  10. }
  11.  
  12. var objJ: ClassJ? = ClassJ()
  13. objJ?.closure()
  14. // 因为闭包引用了类的成员属性,导致实例无法释放,进而导致闭包无法释放,产生循环引用
  15. objJ = nil // 此处并没有打印 deinit 中信息
  16.  

7. Swift 解决闭包产生的循环引用

  1. // Swift5 解决闭包产生的循环引用
  2. class ClassK {
  3. var field = "field k"
  4. lazy var closure: () -> Void = {
  5. // 使用捕获列表对 self 进行无主引用的转换
  6. [unowned self] () -> Void in
  7. print(self.field)
  8. }
  9. deinit {
  10. print("deinit ClassK")
  11. }
  12. }
  13.  
  14. var objK: ClassK? = ClassK()
  15. objK?.closure()
  16. objK = nil // deinit ClassK
  17.  

8. Swift 自定义异常类型

  1. // Swift5 自定义异常类型
  2. enum CustomError: Error {
  3. case ErrorOne
  4. case ErrorTwo
  5. case ErrorThree
  6. }
  7.  
  8. print("error")
  9. //throw CustomError.ErrorOne // 抛出的异常未捕获会终止,不会打印 complete
  10. print("complete")
  11.  

9. Swift do-catch 捕获异常,try 执行会抛异常的函数

  1. // Swift5 使用 do-catch 捕获异常,try 执行会抛异常的函数
  2. // 通过函数抛出异常
  3. func funcError() throws -> String {
  4. throw CustomError.ErrorTwo
  5. }
  6.  
  7. // 使用 do-catch 捕获异常
  8. do {
  9. // 使用 try 执行可能会抛出异常的函数
  10. try funcError()
  11. } catch CustomError.ErrorOne {
  12. print("ErrorOne")
  13. } catch CustomError.ErrorTwo {
  14. print("ErrorTwo")
  15. } catch CustomError.ErrorThree {
  16. print("ErrorThree")
  17. }
  18.  
  19. // 使用 try? 将函数执行的结果映射为 Optional 类型
  20. let result = try? funcError()
  21. if (result == nil) {
  22. print("exec failed")
  23. }
  24.  
  25. // try! 强行终止异常的传递,如果发生异常,则程序中断
  26. // try! funcError()

10. Swift 函数延时执行结构

  1. // Swift5 函数延时执行结构:避免在抛异常的时候,保证某些必须的代码块要执行,如释放资源
  2. func lazyFunc() throws -> Void {
  3.  
  4. defer {
  5. // 函数结束时会得到执行
  6. print("lazy part of func")
  7. }
  8. print("exec lazyFunc")
  9. throw CustomError.ErrorThree
  10. }
  11.  
  12. // exec lazyFunc
  13. // lazy part of func
  14. try? lazyFunc()
  15.  

GitHub 源码:Reference&Error.playground

到此这篇关于Swift 列举内存管理与异常处理具体代码的文章就介绍到这了,更多相关Swift 内存管理与异常处理内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号