Cocoa阻止作为强指针vs副本 [英] Cocoa blocks as strong pointers vs copy

查看:111
本文介绍了Cocoa阻止作为强指针vs副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾经用过指针的块做了几次,因为我有强引用



我听说你应该使用copy,但在处理块作为指针,而不是与原始对象?



我从来没有得到一个抱怨从编译器,我不应该使用

  @property(nonatomic,strong)MyBlock块; 

但应使用

  @property(nonatomic,copy)MyBlock块; 

据我所知,块只是一个对象, / p>

解决方案

短回答



是完全正确的,在当前ARC代码中没有必要使用 copy strong 财产是罚款。例如,局部和全局变量。



长答案



与其他对象不同,块可以存储在堆栈上,这是一种实现优化,因此像其他编译器优化一样,不会对已编写的代码产生直接影响。这种优化有利于一个常见的情况,其中块被创建,作为方法/函数参数传递,由该函数使用,然后被丢弃 - 块可以被快速地分配在堆栈上,然后被处理而没有堆(动态存储器池)

(a)在堆栈上创建,(b)在拥有函数/方法返回时被自动销毁,并且(c)可以被传递给由拥有函数调用的方法/函数。在拥有函数/方法返回后,本地变量的地址无法存储和使用。变量不再存在。



em>对象预期会超过它们的创建函数/方法(如果需要),所以与局部变量不同,它们被分配在上,并且不会基于它们的创建函数/方法返回而是基于它们是否仍然需要 - 并且这里的需要由ARC自动确定。



在堆栈上创建块可以优化常见的情况但它也会导致一个问题 - 如果块需要超过它的创建者,如对象经常做的那样,那么它必须在创建者堆栈被销毁之前移动到堆。



当块实现首次发布时,堆栈上存储块的优化对程序员是可见的,因为当时的编译器在需要时无法自动处理将块移动到堆中 - 程序员不得不使用函数 block_copy()自己做。



虽然这种方法可能不是在低级C世界(和块都是C构造),有高级Objective-C程序员手动管理编译器优化真的不好。由于苹果发布了更新版本的编译器改进的地方。早期程序员被告知可以用 [block copy] 替换 block_copy(block) -C对象。然后编译器开始根据需要自动复制块,但这并不总是正式记录。



没有必要手动复制块从堆栈为虽然苹果不能嘲笑它的起源,并指这样做是最佳实践 - 这当然是有争议的。在2014年9月的最新版本中,Apple的使用块,他们说块值属性应该使用 copy ,但随后立即清除( emphasis 添加):

$ b $注意:应该指定copy作为属性属性,因为需要复制块以跟踪其捕获的状态原始范围。 这不是你使用自动引用计数时需要担心的问题,因为它会自动进行,但是property属性的最佳做法是显示结果行为。


没有必要显示结果行为 - 首先在堆栈上存储块是一个优化 对代码是透明的 - 就像其他编译器优化一样,代码应该在没有程序员参与的情况下获得性能优势。



只要使用ARC和当前Clang编译器您可以像其他对象一样处理块,并且块是不可变的,这意味着您不需要复制它们。信任苹果,即使他们似乎是怀旧的好的旧日子,当我们手工做的事情,并鼓励你离开历史提醒在你的代码, copy 不是需要。



您的直觉是对的。



HTH


I did work several times with blocks as with pointers to which i had strong reference

I heard that you should use copy, but what is the implication in working with blocks as pointers and not with the raw object?

I never got a complain from the compiler, that i should not use

@property (nonatomic, strong) MyBlock block;

but should use

@property (nonatomic, copy) MyBlock block;

as far as i know, the block is just an object, so why to preferrer copy anyway?

解决方案

Short Answer

The answer is it is historical, you are completely correct that in current ARC code there is no need to use copy and a strong property is fine. The same goes for instance, local and global variables.

Long Answer

Unlike other objects a block may be stored on the stack, this is an implementation optimisation and as such should, like other compiler optimisations, not have direct impact on the written code. This optimisation benefits a common case where a block is created, passed as a method/function argument, used by that function, and then discarded - the block can be quickly allocated on the stack and then disposed of without the heap (dynamic memory pool) being involved.

Compare this to local variables, which (a) created on the stack, (b) are automatically destroyed when the owning function/method returns and (c) can be passed-by-address to methods/functions called by the owning function. The address of a local variable cannot be stored and used after its owning function/method has return - the variable no longer exists.

However objects are expected to outlast their creating function/method (if required), so unlike local variables they are allocated on the heap and are not automatically destroyed based on their creating function/method returning but rather based on whether they are still needed - and "need" here is determined automatically by ARC these days.

Creating a block on the stack may optimise a common case but it also causes a problem - if the block needs to outlast its creator, as objects often do, then it must be moved to the heap before its creators stack is destroyed.

When the block implementation was first released the optimisation of storing blocks on the stack was made visible to programmers as the compiler at that time was unable to automatically handle moving the block to the heap when needed - programmers had to use a function block_copy() to do it themselves.

While this approach might not be out-of-place in the low-level C world (and blocks are C construct), having high-level Objective-C programmers manually manage a compiler optimisation is really not good. As Apple released newer versions of the compiler improvements where made. Early on it programmers were told they could replace block_copy(block) with [block copy], fitting in with normal Objective-C objects. Then the compiler started to automatically copy blocks off stack as needed, but this was not always officially documented.

There has been no need to manually copy blocks off the stack for a while, though Apple cannot shrug off its origins and refers to doing so as "best practice" - which is certainly debatable. In the latest version, Sept 2014, of Apple's Working with Blocks, they stated that block-valued properties should use copy, but then immediately come clean (emphasis added):

Note: You should specify copy as the property attribute, because a block needs to be copied to keep track of its captured state outside of the original scope. This isn’t something you need to worry about when using Automatic Reference Counting, as it will happen automatically, but it’s best practice for the property attribute to show the resultant behavior.

There is no need to "show the resultant behavior" - storing the block on the stack in the first place is an optimisation and should be transparent to the code - just like other compiler optimisations the code should gain the performance benefit without the programmer's involvement.

So as long as you use ARC and the current Clang compilers you can treat blocks like other objects, and as blocks are immutable that means you don't need to copy them. Trust Apple, even if they appear to be nostalgic for the "good old days when we did things by hand" and encourage you to leave historical reminders in your code, copy is not needed.

Your intuition was right.

HTH

这篇关于Cocoa阻止作为强指针vs副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆