如何在Objective-C的属性中存储块?


77

我想将Objective-C块存储在一个属性中以备后用。我不确定该怎么做,所以我在Google上搜索了一下,关于该主题的信息很少。但是我最终设法找到了解决方案,并且我认为对于像我这样的其他新手来说,值得分享。

最初,我认为我需要手动编写属性才能使用Block_copy和Block_release。

幸运的是,我发现块是NSObjects- copy/- release等效于Block_copy/ Block_release。因此,我可以@property (copy)用来自动生成setters和getters。


1
是否可以将Objective-C块用作属性?这个问题比那里的问题最近。
理查德·罗斯三世

1
完整的示例代码UP-TO-DATE仅向初学者进行了说明:stackoverflow.com/a/20760583/294884
Fattie 2014年

1
对于新读者来说,这个极其古老的问题现在非常令人高兴。您只是说@property(copy)void(^ doStuff)(void); 只不过是复制。现在,这在苹果doco的许多地方都得到了清晰的解释(包括原因)。它再简单不过了;这就是全部答案。实际上,由于您现在仅使用Swift,所以整个问题仅具有历史价值。
Fattie 2015年

Answers:


135

编辑:已针对ARC更新

typedef void(^MyCustomBlock)(void);

@interface MyClass : NSObject

@property (nonatomic, copy) MyCustomBlock customBlock;

@end

@implementation MyClass

@end

MyClass * c = [[MyClass alloc] init];
c.customBlock = ^{
  NSLog(@"hello.....");
}

c.customBlock();

5
有谁知道为什么要使用块(非原子,副本)而不是(非原子,保留)?通常使用保留,而我找不到任何地方解释为什么将复制用于块。
史蒂夫·波特

29
是的,戴夫,真的。我也可以搜索并看到它们。解释含糊不清,就像您使用复制“使它们实际上在堆栈框架中幸存下来”一样。我认为保留对象也可以做到这一点。没有人解释如何堆栈分配块。但是,有评论确实链接到了一篇很好的文章-cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html。请参见“块是有点奇怪的对象”。所以谢谢!
史蒂夫·波特

戴夫(Dave)-我不太确定应该特别使用“非原子”方法。(FWIW-不一定正确!!-最新的Apple doco说您应该使用“复制”-故事的结尾。)很难看出性能可能很重要,并且由于您在此处的帖子几乎是世界上唯一的参考,事情可能就在外面,这很危险。对这个晦涩的问题有什么想法吗?谢谢!
Fattie 2014年

2
@JoeBlow仅在担心从多个队列中同时获取和设置属性的值时才需要原子性。否则没关系。
Dave DeLong 2014年

3
我/我们nonatomic到处使用。它应该是默认的IMO。atomic这会导致更大的二进制文件,更低的性能(在所有访问器上都锁定),并且似乎保证了线程安全性-通常通常必须在比属性访问器更高的级别上解决该问题。
史蒂文·克雷默

101

或者,不使用typedef

@property (copy, nonatomic) void (^selectionHandler) (NSDictionary*) ;


20
需要说明的是,由于语法非常不透明,因此这是一个名为“ selectionHandler”的块属性,它带有NSDictionary *参数并返回void。
Christopher Pickslay 2012年

我认为阅读起来并不难,但是我同意使用typedef看起来更好。我倾向于为通常要传递的参数编写一堆typedef:PFObjectBlock,PFStringBlock,PFArrayBlock,PFErrorBlock等。–
Besi

id,SEL,IMP是否可以进一步简化?
dklt 2012年

9

您可以在从第83页开始的WWDC 2012会话712中找到对此的很好解释。在ARC下保存块的正确方法如下:

@property(strong) my_block_type work;

注意保留周期。解决该问题的一种好方法是在不再需要该块时将其设置为nil:

self.work = nil;

2
仅适用于ARC。在MRC之下,这是错误的。但是copy在MRC和ARC下均可正常运行
newacct 2012年

我认为复制在MRC中的所有情况下都不能很好地工作,但也许在大多数情况下都如此
Jorge Perez 2012年

您使用MRC是正确的,但它不在ARC中。抱歉,我想在先前的评论中说ARC。
豪尔赫·佩雷斯

真的很有趣,关于ARC如何将数据块移出堆栈的任何想法吗?
MonsieurDart 2012年

“ __block yourClass * blockSelf = self”。仅在“工作”属性内使用blockSelf。
MasterBeta
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.