在Objective-C中复制块(即:将它们复制到实例变量)

Rya*_*cox 19 cocoa objective-c objective-c-blocks

我想了解块.当直接传递给方法时,我得到了正常使用它们的方法.我现在感兴趣的是一个块,将它(例如)存储在一个实例变量中并稍后调用它.

块编程指南听起来像我可以做到这一点,通过使用Block_copy/retain来复制块,但是当我尝试运行它时,我崩溃了我的程序.

- (void) setupStoredBlock
{
    int salt = 42;
    m_storedBlock = ^(int incoming){ return 2 + incoming + salt; };
    [m_storedBlock retain];
}
Run Code Online (Sandbox Code Playgroud)

我试着稍后再说:

- (void) runStoredBlock
{
    int outputValue = m_storedBlock(5);
    NSLog(@"When we ran our stored blockwe got back: %d", outputValue);
    [m_storedBlock release];
}
Run Code Online (Sandbox Code Playgroud)

有人有任何见解吗?(或者,有什么东西我没有用积木?)

非常感谢你!

Dav*_*ong 30

你会想要这样做:

- (void) setupStoredBlock
{
    int salt = 42;
    m_storedBlock = Block_copy(^(int incoming){ return 2 + incoming + salt; });
}
Run Code Online (Sandbox Code Playgroud)

  • 啊.没有错误.这是他博客上的bbum:"对于一个尚未被复制的Block,-retain没有意义.它什么都不做.它本来可以用来返回Block的副本,但这可能是-taintain合约的分支超出可接受范围."http://www.friday.com/bbum/2009/08/29/blocks-tips -tricks /所以,是的,你确实需要复制它 - "thetain"在这里不起作用. (8认同)
  • Dave DeLong:确实如此,但仅适用于堆上的块(之前已被复制的块). (3认同)

Jer*_*man 6

当您希望它留在身边时复制一个块.当你完成它时自动释放或释放它.如果你需要很长的拼写方法,请保留它/* NOP */.

@interface Foo : FooSuper {}
@property(copy) int (^storedBlock)(int);
@end

@implementation Foo
@synthesize storedBlock = mStoredBlock;

- (void)setupStoredBlock {
    self.storedBlock = ^{/*...*/};
    // or: mStoredBlock = [^{/*...*/} copy];
    // but this simple implementation violates the atomicity contract
}

- (void)runStoredBlock {
    int result = self.storedBlock(5);
    NSLog(@"%s: result = %d", __func__, result);
}
@end
Run Code Online (Sandbox Code Playgroud)

  • retain只对堆栈块进行无操作.对于堆块,它们确实保留 (2认同)

car*_*min 6

•与所有局部变量一样,堆栈上存在非静态块,并且将从堆栈中弹出,就像任何其他未声明为静态的局部变量一样.

•Block_copy()将块从堆栈复制到堆上,其中存在所有malloc实例.和所有新的/复制方法一样,Block_copy()返回一个堆分配的对象,其保留计数为1.块是一个objectiveC对象,但不像普通对象那样符合.因此,Block_Release()和目标释放方法之间应该没有区别.

•此示例使用块实例的复制方法.因为将Block_copy()的结果分配给id需要一个我不想出错的类型转换.复制方法允许将块变量直接分配给id.

 - (void) setupStoredBlock
{
    int zStackLocalVariable = 42;
    iHeapAllocatedVariable = [^int(int aMore){ return zStackLocalVariable + aMore; } copy];
}
Run Code Online (Sandbox Code Playgroud)

•将对象声明为静态是要求使用代码本身对其进行物理分配.声明为static的块是编译器禁止访问其自身范围之外的变量.由于静态块声明的要求,我假设堆栈上的块与堆中的块有某种不同.

•块是一个客观的c对象,其类的类名和其他相关信息我尚未尝试检索,但是,如Protocol,Object和其他隐藏的objectiveC类,它不符合NSObject.但是,与所有objectiveC对象一样,它必须符合retain/release.ARC还将保留/释放等效项扩展到Core Foundation对象中,如果不是现在,最终可能会延伸到malloc/free分配中.

•我等待彻底探索mikeash.com的真正动机,因为苹果喜欢把我们所有人放在一些物理意义不大的超理论层面上,尽管所有重要的都是物理的.

ARC和块也在这里讨论