首页 > 其他分享 >iOS Swift 的捕获列表 [weak self] 和 [unowned self]

iOS Swift 的捕获列表 [weak self] 和 [unowned self]

时间:2024-10-22 10:47:46浏览次数:1  
标签:闭包 weak 捕获 iOS unowned 引用 self

捕获列表(capture list)是 Swift 中闭包的重要概念之一,用来控制闭包如何捕获和存储其上下文中的外部变量。

捕获行为

在闭包中使用外部变量时,Swift 会自动捕获这些变量的引用。如果这些变量是引用类型(如类实例),闭包会持有它们的强引用,可能导致强引用循环,即内存泄漏。

捕获列表允许你明确指定闭包应该如何捕获这些外部变量,特别是在需要避免强引用循环时,你可以使用捕获列表来指定变量的捕获方式,如使用 weak 或 unowned

捕获列表的语法

捕获列表在闭包表达式的起始位置,放在方括号 [] 中。每个捕获项都可以包含变量名、以及如何捕获该变量(weakunowned 等)。

语法格式:

{ [捕获列表] (参数) -> 返回类型 in
    // 闭包体
}

在 Swift 中,weak 和 unowned 都用于防止强引用循环,但它们有不同的特性和使用场景。核心区别在于,当引用的对象被释放时,它们的行为不同:

1. weak 引用

  • 自动设为 nil:当被引用的对象被释放时,weak 引用会自动变为 nil
  • 可选类型:由于 weak 引用可能会在对象被释放后变成 nil,因此它必须是可选类型Optional)。
  • 使用场景:通常用于避免强引用循环,特别是在对象的生命周期可能比引用的闭包短时(即闭包执行时对象可能已被释放)。
class MyClass {
    var value = 10
    func printValue() {
        let closure = { [weak self] in
            print(self?.value ?? 0)
        }
        closure() // 输出 10
    }
}

let myClass = MyClass()
myClass.printValue()
//在这个例子中,捕获列表 [weak self] 指定 self 以弱引用的方式捕获,避免了闭包对 self 的强引用,防止强引用循环。如果 self 在闭包执行时被释放,self 会变为 nil,因此使用 self? 来安全地访问其属性。

2. unowned 引用

  • 不会设为 nilunowned 引用不会变为 nil,即使被引用的对象已经被释放。
  • 非可选类型unowned 不需要声明为可选类型,因此它在使用时总是会假设对象存在。
  • 使用场景:适用于闭包执行期间,对象一定会存在的情况。对象被释放后,再访问 unowned 引用会导致程序崩溃(runtime error)。
class MyClass {
    var value = 10
    func printValue() {
        let closure = { [unowned self] in
            print(self.value)
        }
        closure() // 输出 10
    }
}

let myClass = MyClass()
myClass.printValue()
//unowned 表示闭包不持有对象的强引用,但假设对象在闭包执行期间仍然存在。如果在 unowned 的场景中访问已经释放的对象,会发生运行时崩溃。

总结区别:

特性weakunowned
是否会变为 nil 是的,自动变为 nil 否,不能变为 nil
是否必须是可选类型 是,必须为可选类型(Optional 否,不需要可选类型
是否会导致崩溃 不会,因为对象释放后会变成 nil 会,如果对象已经释放,访问 unowned 会崩溃
使用场景 对象生命周期可能比闭包短 对象生命周期在闭包执行期间一定存在

何时使用:

  • 使用 weak:当你不确定对象的生命周期,可能会在闭包执行时已经被释放的情况下,使用 weak。(弱引用)
  • 使用 unowned:当你确定对象在闭包的整个执行过程中都不会被释放时,可以使用 unowned。(无主引用)

 

标签:闭包,weak,捕获,iOS,unowned,引用,self
From: https://www.cnblogs.com/someonelikeyou/p/18492137

相关文章

  • iOS开发基础-iPhone所有机型的硬件生产代号与对应机型
    以下是根据公开资料整理的iPhone所有机型的硬件生产代号与对应机型的列表。硬件生产代号对应机型iPhone1,1iPhone2GiPhone1,2iPhone3GiPhone2,1iPhone3GSiPhone3,1iPhone4(GSM)iPhone3,2iPhone4(GSMRev.A)iPhone3,3iPhone4(CDMA)iPh......
  • 【ios】使用TestFlight将app分发给测试人员(超详细)
    我的环境:macos系统是Ventura13.0xcode是14.2(后面发现至少需要15版本的xcode才能上传app)证书生成  可以通过xcode生成Distribution类型的证书,如果你已经有的话那就忽略,这个证书也是备案时所需的。我是已经有证书了,后续的步骤使用的是之前已有备案证书。这个步骤只是放......
  • iOS系统下Window.open()方法失效问题
    在iOS系统下,window.open()方法失效的问题是一个常见的挑战,主要原因是iOS的安全机制和浏览器策略。以下是详细的原因分析和解决方案:原因分析安全机制拦截:iOS的Safari浏览器为了防止弹出广告和恶意窗口,对window.open()方法进行了限制。如果window.open()不是由用户直接交互触发的......
  • Axios和Fetch区别
    1、基本用法GETPOST(Json)POST(formdata)数据流中止请求请求超时进度监控通用配置拦截器2、区别AxiosFetch底层实现第三方库,基于XMLHttpRequest现代浏览器自带的底层API特点使用更简洁使用更灵活体积非浏览器自带,需安装,占用一些体积浏......
  • VMware Fusion 13.6.1 OEM BIOS 2.7 - 在 macOS 中运行 Windows 虚拟机的最佳方式
    VMwareFusion13.6.1OEMBIOS2.7-在macOS中运行Windows虚拟机的最佳方式VMwareFusion13原版App中集成OEMBIOS请访问原文链接:https://sysin.org/blog/vmware-fusion-13-oem/查看最新版。原创作品,转载请保留出处。作者主页:sysin.org2024-10-11,版本13.6.1例......
  • iOS开发框架--MyLayout
    MyLayout框架不仅支持Objective-C,也可以在Swift中使用。通过MyLayout,可以使用面向对象的方式来创建和管理视图的布局,简化了AutoLayout中繁琐的约束设置流程。在Objective-C中,MyLayout提供了相同的布局类型和属性,使用方式稍有不同,主要是语法和调用方式上的差异。先介......
  • 【Agent系列】从论文到源码解析Self-Ask 以及数据构建带来的启发
    前言一、Self-Ask解决了什么二、Self-Ask的理论实现三、从源码看Self-Ask的实现四、从实验结果看LLM的内部机制五、数据集的构建细节六、资料链接总结前言Self-Ask对LLM的推理能力进行了实验评估,并且提出了一种follow-up范式来提升LLM的2跳推理能力,为了进一步提升回答准确率......
  • 苹果(ios)应用ipa文件上传到苹果商店app store步骤
    这篇文章的前提是你已经用苹果打包证书打包好ipa文件,准备将ipa文件上传到appstore。假如你还没有苹果证书,还没有打包好ipa文件,你还不知道证书怎么创建,可以参考这篇文章先生成证书和证书profile文件:https://www.cnblogs.com/handsome0916/p/18329211然后你到iosdevcenter,也......
  • iOS Swift 里的捕获变量
    在Swift中,闭包不仅可以作为函数的简洁表达方式,还能捕获和存储其所在上下文中的常量和变量。捕获的变量会随着闭包的生命周期延续,即使这些变量已经超出了原作用域,它们仍然可以在闭包中被访问和修改。这种行为被称为闭包捕获,是闭包的核心特性之一。//变量值捕获funcmakeIncrem......
  • weakmap、weakset、内存泄漏
    weakmap、weakset都是ES6的新增的数据结构WeakMapWeakMap对象是键值对的集合,提供了一种键值对的存储机制。它的键必须是对象类型,值可以是任意类型。它的键被弱保持,也就是说,当其键所指对象没有其他地方引用的时候,它会被GC回收掉。WeakMap提供的接口与Map相同。与Map......