草庐IT

ios - 无法理解 Objective-C block 文档

coder 2023-09-22 原文

我目前无法理解 Obj-C block 和 __block 存储类型的基础知识。 来自以下文档:

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6

我正在尝试理解以下段落和示例:

复制 block 时,它会创建对 block 中使用的对象变量的强引用。如果您在方法的实现中使用 block :

如果你通过引用访问一个实例变量,那么强引用就是self; 如果按值访问实例变量,则会对该变量进行强引用。 以下示例说明了两种不同的情况:

dispatch_async(queue, ^{
    // instanceVariable is used by reference, a strong reference is made to self
    doSomethingWithObject(instanceVariable);
});

id localVariable = instanceVariable;
dispatch_async(queue, ^{
    /*
      localVariable is used by value, a strong reference is made to localVariable
      (and not to self).
    */
    doSomethingWithObject(localVariable);
});

要覆盖特定对象变量的此行为,您可以使用 __block 存储类型修饰符对其进行标记。

我的问题:

  1. 一个示例“通过引用访问”而另一个示例如何通过变量访问?为什么 localVariable 是“按值使用的”?
  2. 文档中的“强烈引用 self ”是什么意思?指的是哪个“自己”?
  3. 如果我在第二个示例中将 __block 存储类型添加到 localVariable,我是否错误地假设 block 关闭了变量,因此它将它保留在堆中直到 block 被释放?还有哪些事情正在发生?

谢谢!

最佳答案

How exactly is one example "accessed by reference" while the other one is accessed by variable? Why is localVariable "used by value?"

理解这一点的一种方法如下:

  1. 当您在方法中定义的 block 中使用局部变量时,发生的情况是该变量的内容被复制到某个 block 专用内存中,以便在执行该 block 时(在方法退出);在这个意义上,我们可以谈论“按值”访问(如:值被复制);从语法上讲,编译器不知道 localVariable 的内容指的是什么,因此它的值被这样处理;

  2. 当在类的方法中定义的 block 中直接访问 instanceVariable 时,编译器知道我们正在访问正在执行该方法的同一个对象,因此不需要复制任何东西,因为对象的生命周期比找到 block 的方法长;但是我们需要确保在执行 block 时该对象仍然存在,因此我们获得了对它的强引用。

现在,关于“通过引用”的使用:在第一种情况下,您获得了对类成员的引用的副本:如果您可以更改它的值(但您不能,因为编译器禁止这样做), 你只是在修改 block 私有(private)副本,所以原始对象不受影响。

在第二种情况下,您可以修改 instanceVariable 的值(例如:它是 nil 并且您分配了一个通过它引用的对象),这将影响定义 block 时执行该方法的对象。

What does the doc mean by "a strong reference is made to self"? Which "self" is it referring to?

self 是当前正在执行找到该 block 的方法的对象。进行强引用仅意味着(用 ARC 的说法)对象的保留计数增加(以确保某些其他实体不能通过释放它来导致它被释放)。

If I add the __block storage type to localVariable in the second example, am I wrong to assume that the block closes over the variable, so it keeps it around in heap until block is released? What other things are happening?

使用 __block 使变量始终“通过引用”访问,因此您可以修改它们。

这是他们的处理方式:

__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus, the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame (for example, by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.

As an optimization, block storage starts out on the stack—just like blocks themselves do. If the block is copied using Block_copy (or in Objective-C when the block is sent a copy), variables are copied to the heap. Thus, the address of a __block variable can change over time.

关于ios - 无法理解 Objective-C block 文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14463580/

有关ios - 无法理解 Objective-C block 文档的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  3. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  4. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  5. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  6. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

  7. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  8. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  9. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  10. ruby-on-rails - 无法让 rspec、spork 和调试器正常运行 - 2

    GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'

随机推荐