不同的闭包在快速保留周期中给出不同的结果

2023-12-25

我正在阅读 Apple 的 Swift 编程语言指南。在关于闭包的强引用循环的部分中,我尝试了一种不同类型的闭包,但它没有给出预期的输出。

class HTMLElement {

let name: String
let text: String?

lazy var asHTML : String = {

    //[unowned self] in

    if let text = self.text {
        return "<\(self.name)>\(text)</\(self.name)>"
    } else {
        return "<\(self.name) />"
    }
}()

init(name: String, text: String? = nil) {
    self.name = name
    self.text = text
}

deinit {
    println("\(name) is being deinitialized")
}

}

 var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
 println(paragraph!.asHTML)
 paragraph = nil

该代码的输出是:

<p>hello, world</p>
p is being deinitialized

即使没有 [unowned self] 也会打印“p is being deinitialized”

指南中的代码是:

class HTMLElement {

let name: String
let text: String?

lazy var asHTML: () -> String = {
    [unowned self] in
    if let text = self.text {
        return "<\(self.name)>\(text)</\(self.name)>"
    } else {
        return "<\(self.name) />"
    }
}

init(name: String, text: String? = nil) {
    self.name = name
    self.text = text
}

deinit {
    println("\(name) is being deinitialized")
}

}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
 println(paragraph!.asHTML)
 paragraph = nil

仅当添加 [unowned self] 语句时,才会打印 deinitialiser 消息。

这两种闭包有什么区别?


好问题!为了探索它,我们应该将测试用例简化到演示它所需的最低限度:

// First case, a lazy string
class LazyVar {
    let name = "LazyVar"
    lazy var lazyName : String = { return self.name }()
    deinit {
        println("\(name) is being deinitialized")
    }
}

var lazyVar: LazyVar? = LazyVar()
println(lazyVar?.lazyName)
lazyVar = nil // Calls deinit

// Second case, a lazy ()->String
class LazyFunc {
    let name = "LazyFunc"
    lazy var lazyFunc: () -> String = {
        // [unowned self] in    // <-- This would break the loop
        return self.name
    }
    deinit {
        println("\(name) is being deinitialized")
    }
}

var lazyFunc: LazyFunc? = LazyFunc()
println(lazyFunc?.lazyFunc())
lazyFunc = nil // Doesn't call deinit

在第一种情况下,没有永久的保留循环。当您访问lazyName,评估闭包{ return self.name }。该闭包捕获了self,计算一个字符串,并返回该字符串。该字符串被分配给属性。我们现在已经完成了关闭,所以它被释放了,它也被释放了self。请注意,这里有一个简短的保留循环,但没关系。它最终会被打破,这才是最重要的。

在第二种情况下,存在永久保留循环。当您访问lazyFunc(),它调用一个闭包来创建一个新的关闭。新的关闭是{return self.name},并将其分配给该属性。并且该关闭保留了self,永不中断的保留循环也是如此。添加[unowned self] in to lazyFunc如标记所示,将为您打破循环。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

不同的闭包在快速保留周期中给出不同的结果 的相关文章

随机推荐

  • 数据库架构更改后更新 LINQ to SQL 类的最佳方法

    我在一个项目中使用 LINQ to SQL 类 该项目的数据库设计仍然有些变化 是否有一种简单的方法可以将类与架构同步 或者如果表设计发生更改 我是否需要手动更新类 您可以使用 SQLMetal exe 生成 dbml 和 或 cs vb
  • 如何使用 Tridion Resolver 从发布中删除项目?

    我正在尝试为组件实现自定义解析器 如 Chris 所描述的 http www tridiondeveloper com the story of sdl tridion 2011 custom resolver and the alloww
  • 将 HTML 转换为 contentEditable 中的纯文本

    我有一个contentEditable我删除粘贴内容的格式on paste 通过捕捉事件 然后我聚焦一个文本区域 将内容粘贴到其中 然后复制该值 答案几乎来自here https stackoverflow com a 10551358 1
  • 直接在 Azure Datalake 中将 Python Dataframe 写入 CSV 文件

    我已将 Excel 文件导入到 pandas 数据框中 并完成了数据探索和清理过程 我现在想要将清理后的数据帧写入 csv 文件回 Azure DataLake 而不先将其保存为本地文件 我正在使用熊猫3 我的代码如下所示 token li
  • 任意精度小数算术中的浮点数与有理数 (C/C++)

    由于实现 AP 分数的方法有两种 一种是模拟 AP 的存储和行为double数据类型 仅具有更多字节 另一种是使用现有的整数 APA 实现将小数表示为有理数 即表示为一对整数 分子和分母 这两种方式中哪一种更有可能提供高效的算术在性能方面
  • 如何用 C 语言编写布尔表达式计算器?

    假设我在文本文件中有一个这样的字符串 var1 AND var2 AND var3 OR var4 AND var5 OR var6 AND var7 将其解析为 C 程序并正确处理和设置变量后 它将最终看起来像这样 1 AND 0 AND
  • MVC、DbContext 和多线程

    关于这些主题有很多问题 每个人都有自己的看法 也许有人可以就以下问题给我一个很好的答案 我有一个 Asp NET MVC Web 服务 它使用 EntityFramework 来访问数据库 有一个控制器 每次用户向 Web 服务发出请求时都
  • Ignite C++ 客户端用于 cassandra 集成

    我正在开发一个数据通信应用程序 我想通过 ignite c 与 cassandra 进行通信 当我尝试将数据放入 cassandra 时 它工作正常 但我无法从中获取数据 这是我的代码 test h namespace ignite nam
  • 如何延迟未命名对象的销毁?

    我正在使用TempDir struct https doc rust lang org tempdir tempdir struct TempDir html search 在磁盘上创建和删除文件夹 这TempDir除了其构造之外 代码中并
  • 如何增加 android Log 类的控制台输出

    对于 Android 平台上的默认 Log 控制台输出的字符数量有限 大约等于 3000 多一点 因此 如果消息长度超过 3000 个字符 则不会在屏幕上显示 我还没有找到比这更好的解决方案 public class Log private
  • WPF 和 WCF 数据服务在查询级别进行身份验证?

    所以 我发誓我对如何保护 WCF 数据服务完全感到困惑 在这方面 是否有一种简化的检查方法 以确保将数据发送到 WCF 服务的客户端经过身份验证 确保客户端本身是我编写的客户端 而不是某个模拟客户端 有什么网址可以帮助我解决这个问题吗 我使
  • 为什么在 Python 类定义的生成器中会出现此 NameError?

    在 Python 3 5 0 中 这段代码 a 1 2 class Foo object b 3 4 c tuple i j for j in b for i in a d tuple i j for i in a for j in b 产
  • 用于测试系统稳定性的函数,接收预测的时间序列作为输入

    我想编写一个函数 获取时间序列和标准差作为参数 并返回看起来像预测的调整后的时间序列 通过这个函数 我想测试一个系统的稳定性 该系统获取天气的预测时间序列列表作为输入参数 我对此类函数的方法如下所述 vector
  • getimagesize() 与 finfo_file() 用于检测图像类型?

    有时图像没有扩展名 但仍然有效 我有一个文件上传表单 需要检测文件类型以将其与我的白名单进行比较 我知道我不能信任从浏览器发送的 mime 类型 因此从我所做的研究来看 这两个选项似乎是可用的 它们仅在上传文件后才起作用 info geti
  • 如何在 TypeScript 中访问静态方法

    我正在尝试这样做 但它没有像我预期的那样工作 我使用的是 AMD 选项 logger ts export class Logger static log message string do stuff main ts import logg
  • Javascript 性能 - Dom Reflow - Google 文章

    有人可以向我证明给出的建议吗here http code google com speed articles javascript dom html 复制如下 关于在更改 dom 元素之前删除它们然后重新插入它们的速度更快 作为证明 我想看
  • R 中的加权随机数生成

    我正在尝试生成一组固定范围内的 100 个随机整数 一个可以由 1 到 3 之间的 100 个数字组成 并具有获得 1 2 和 3 之一的特定概率 任何帮助 将不胜感激 See sample 例如 sample c 1 2 3 size 1
  • OCaml中的fold_tree

    你可能知道 OCaml中有一些高阶函数 例如fold left fold right filter等 在我的函数式编程课程中 引入了名为fold tree的函数 它类似于fold left right 不是在列表上 而是在 二元 树上 它看
  • .NET 4.5 异步等待和重载方法

    我有一个异步方法 public async Task
  • 不同的闭包在快速保留周期中给出不同的结果

    我正在阅读 Apple 的 Swift 编程语言指南 在关于闭包的强引用循环的部分中 我尝试了一种不同类型的闭包 但它没有给出预期的输出 class HTMLElement let name String let text String l