3

在这个 Apple 参考中,objective-c 中有一个 Blocks 对象的概念概述:

http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Blocks/Blocks.pdf

但是,它并没有真正解释两个与我有关且可能与其他人有关的主题。第一个问题是这样的:我可以将 nil 分配给 Block 引用吗?或者我应该使用NULL?或者我不能使用它们?

第二个问题在于内存管理领域。比如说,我已经声明了这样一个在堆栈上创建块对象的方法。

-(void)makeTheClass
{
    TheClass *object = [[TheClass alloc] init];

    object.blockReference = ^(void) { return nil; } 
}

这个对象是在某个范围内创建的,在它离开后将被销毁。但是 TheClass 对象实际上将存储对这个(几乎被破坏的)块的引用:

typedef id (^WeirdBlockType)(void);

@interface TheClass {
    WeirdBlockType blockReference;   
}

如何为这样的块声明类属性?这两者有什么区别:

@property (nonatomic, retain) WeirdBlockType blockReference;
@property (nonatomic, copy)   WeirdBlockType blockReference; 

?

在 Apple 文档中明确指出,块复制将块移动到堆中。但如果我只是保留它呢?超出makeTheClass方法范围后会被销毁吗?

4

2 回答 2

2

好吧,我找到了解决方案。感谢 Gojan 的回答,但实际上他在一个地方错了:

维瓦是对的。在块完全移动到堆之前,保留在块上没有任何效果Block_copy,并且只会完成这样的任务。

也许块不是唯一在堆栈中无法保留的对象;但是当您默认alloc在堆上创建(和init)任何子NSObject类实例时,您并不关心它 -照常工作。默认情况下,块对象是在堆栈上创建的,这就是为什么工作有点出乎意料的原因。retain

谢谢大家!

于 2010-11-14T10:27:25.620 回答
0

我可以将 nil 分配给 Block 引用吗?或者我应该使用NULL?

nil 可以读作“空id类型”,而 NULL 的定义类似于((void *)0). 这里的区别在于上下文。如果你正在使用基于 NSObject 的对象,你应该使用 nil。

对于块,您应该使用 nil,因为您可以与块交互,就像它是一个 NSObject 一样(您可以保留它,释放它等)。但是如果你使用 NULL 它应该可以工作。

如何为这样的块声明类属性?这两者有什么区别:

@property (nonatomic, retain) WeirdBlockType blockReference;
@property (nonatomic, copy)   WeirdBlockType blockReference; 

?

在文档中说:

如果您使用的是 Objective-C,您可以发送块复制、保留和释放(和自动释放)消息。

所以这两个声明都是有效的,但如果你问我我更retain喜欢copy.

综上所述:

块被视为同时定义和实例化的对象(运行时),因此在获得对它的持久引用后,您可以像任何其他对象一样认为该引用。

于 2010-11-13T13:32:55.907 回答