草庐IT

swift - 协议(protocol)对保留计数有影响吗?

coder 2023-09-14 原文

我有一个非常简单的代码。我有目的地用委托(delegate)创建一个内存循环。尝试观察和学习如何使用 Xcode 的 Memory Graph。

我不明白为什么在连接部分,Xcode 说有 3 个连接。应该只有 2 个。

如果我用 with 闭包创建一个内存循环,那么它将显示 2 个连接。

我的委托(delegate)泄露代码:

protocol SomeDelegate {
    func didFinishSomething()
}

class Something {
    var delegate: SomeDelegate?
}

class ViewController: UIViewController, SomeDelegate {

    var x = Something()

    override func viewDidLoad() {
        super.viewDidLoad()
        print("view did load")
        x.delegate = self
    }

    func didFinishSomething() {
        print("something was finished")
    }

    deinit {
        print("dellocated!!!")
    }
}

我将该 View 推送到 navigationController,然后返回。

这 2 个委托(delegate)对象的内存地址略有不同,仅相差 +16


似乎与委托(delegate)对象是协议(protocol)有关。因为当我删除协议(protocol)时,它会减少到 2:

class Something2 {
    var delegate: ViewController?
}

class ViewController: UIViewController {

    var x = Something2()

    override func viewDidLoad() {
        super.viewDidLoad()
        print("view did load")
        x.delegate = self
    }

    deinit {
        print("dellocated!!!")
    }
}

最佳答案

我很确定这只是 Xcode 弄糊涂了。协议(protocol)值不应导致对普通强引用的任何额外保留,因为内存管理操作通过存储在存在容器中的类型元数据转发到基础值。

这是一个在 Xcode 的内存图调试器中重现相同结果的最小示例:

protocol P {}

class C : P {
  var d: D?
}

class D {
  var p: P?
}

func foo() {
  let c = C()
  let d = D()
  c.d = d
  d.p = c
}

foo()

print("insert breakpoint V")

print("insert breakpoint ^")

如果您在打印语句之间插入一个断点并查看内存图,您将看到 3 个连接。有趣的是,如果在分配 d.p 之后分配 c.d,您将看到 2 个连接的正确结果。

但是,如果我们在 swift_retainswift_release 上设置符号断点,以便查看强保留/释放 Swift ARC 流量(同时打印出存储在 中的值>%rdi 寄存器,貌似是x86上用来传递参数的寄存器):

然后在调用 foo() 后立即插入一个断点,我们可以看到在这两种情况下,每个实例都保留 +2 并释放 -2(记住它们进入世界作为 +1 保留,从而使它们保持分配状态):

swift_retain 1
     rdi = 0x000000010070fcd0
swift_retain 2
     rdi = 0x000000010070fcd0
swift_release 1
     rdi = 0x0000000000000000
swift_release 2
     rdi = 0x000000010070fcd0
swift_retain 3
     rdi = 0x00000001007084e0
swift_retain 4
     rdi = 0x00000001007084e0
swift_release 3
     rdi = 0x00000001007084e0
swift_release 4
     rdi = 0x000000010070fcd0
swift_release 5
     rdi = 0x00000001007084e0

所以看起来问题出在 Xcode 上,而不是 Swift。

关于swift - 协议(protocol)对保留计数有影响吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56227192/

有关swift - 协议(protocol)对保留计数有影响吗?的更多相关文章

  1. ruby-on-rails - Ruby on Rails 计数器缓存错误 - 2

    尝试在我的RoR应用程序中实现计数器缓存列时出现错误Unknownkey(s):counter_cache。我在这个问题中实现了模型关联:Modelassociationquestion这是我的迁移:classAddVideoVotesCountToVideos0Video.reset_column_informationVideo.find(:all).eachdo|p|p.update_attributes:videos_votes_count,p.video_votes.lengthendenddefself.downremove_column:videos,:video_vot

  2. ruby - 使用多个数组创建计数 - 2

    我正在尝试按0-9和a-z的顺序创建数字和字母列表。我有一组值value_array=['0','1','2','3','4','5','6','7','8','9','a','b','光盘','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','','u','v','w','x','y','z']和一个组合列表的数组,按顺序,这些数字可以产生x个字符,比方说三个list_array=[]和一个当前字母和数字组合的数组(在将它插入列表数组之前我会把它变成一个字符串,]current_combo['0','0','0']

  3. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  4. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  5. .net - .NET 将如何影响 Python 和 Ruby 应用程序? - 2

    我很好奇.NET将如何影响Python和Ruby应用程序。用IronPython/IronRuby编写的应用程序是否会非常特定于.NET环境,以至于它们实际上将变得特定于平台?如果他们不使用任何.NET功能,那么IronPython/IronRuby相对于非.NET同类产品的优势是什么? 最佳答案 我不能说任何关于IronRuby的东西,但是大多数Python实现(如IronPython、Jython和PyPy)都试图尽可能忠实于CPython实现。不过,IronPython正在迅速成为这方面的佼佼者之一,并且在PlanetPyth

  6. Ruby 计数数组对象,如果对象包含值 - 2

    我有一个数组:array=['Footballs','Baseball','football','Soccer']而且我需要计算看到Football或Baseball的次数,无论大小写和复数形式如何。这是我尝试做的,但没有成功:array.count{|x|x.downcase.include?'football'||x.downcase.include?'baseball'}编写这段代码的正确或更好的方法是什么?我正在寻找3作为答案。 最佳答案 我会将count与一个block结合使用,该block根据与您正在寻找的约束相匹配的正

  7. ruby - HTTP POST 上的 SSL 错误(未知协议(protocol)) - 2

    尝试通过SSL连接到ImgurAPI时出现错误。这是代码和错误:API_URI=URI.parse('https://api.imgur.com')API_PUBLIC_KEY='Client-ID--'ENDPOINTS={:image=>'/3/image',:gallery=>'/3/gallery'}#Public:Uploadanimage##args-Theimagepathfortheimagetoupload#defupload(image_path)http=Net::HTTP.new(API_URI.host)http.use_ssl=truehttp.verify

  8. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  9. ruby - 是否有 chrome 开关来抑制 'external protocol request' ? - 2

    是否有chrome开关来抑制“外部协议(protocol)请求”?我正在使用selenium-ruby​​-watirwebdriver自动化应用程序。我在网上搜索了绕过此窗口和对话的解决方案:http://productforums.google.com/forum/#!topic/chrome/K22hXwRy6zQ概述了我们如何手动执行此操作。但是对于Selenium-Chrome-Ruby,我需要通过可能设置一个chrome开关(chorme开关列表:=http://src.chromium.org/svn/trunk/src/chrome/common/chrome_swit

  10. ruby - AWS 上远程机器上的进程计数 - 2

    我正在为在AmazonEC2实例上运行的应用程序设计一个AutoScaling系统。应用程序从SQS读取消息并对其进行处理。AutoScaling系统将监控两件事:SQS中的消息数量,所有EC2机器上运行的进程总数。例如,如果SQS中的消息数量超过3000,我希望系统自动缩放,创建一个新的EC2实例,在其上部署代码,当消息数量低于2000时,我希望系统终止EC2实例.我正在用Ruby和Capistrano做这件事。我的问题是:我无法找到一种方法来确定在所有EC2机器上运行的进程数并将该数字保存在变量中。你能帮帮我吗? 最佳答案 您可

随机推荐