【问题标题】:How to store blocks in properties in Objective-C?如何在 Objective-C 的属性中存储块?
【发布时间】:2011-05-04 04:02:26
【问题描述】:

我想将objective-c 块存储在一个属性中以供以后使用。我不知道该怎么做,所以我用谷歌搜索了一下,关于这个主题的信息很少。但我最终设法找到了解决方案,我认为它可能值得像我这样的其他新手分享。

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

幸运的是,我发现blocks are NSObjects- copy/- release 等价于Block_copy/Block_release。所以我可以使用@property (copy) 来自动生成setter & getter。

【问题讨论】:

  • Can I use Objective-C blocks as properties? 可能重复这个问题比那里的问题更新。
  • 完整的示例代码,UP-TO-DATE,为初学者简单解释:stackoverflow.com/a/20760583/294884
  • 对于新读者来说,这个非常古老的问题现在已经过时了。你只是说 @property (copy)void (^doStuff)(void); 没有更多或更少的副本。现在,在苹果 doco 的许多地方都清楚地解释了这一点(包括为什么)。再简单不过了;这就是全部答案。事实上,整个问题仅具有历史价值,因为您现在只使用 Swift。

标签: objective-c objective-c-blocks


【解决方案1】:

编辑:为 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();

【讨论】:

  • 有人知道为什么你应该使用(非原子,复制)而不是(非原子,保留)的块吗?通常使用保留,但我找不到任何地方解释为什么要对块使用副本。
  • 是的,戴夫,真的。我也可以搜索并看到那些。解释很模糊,就像您使用复制“使它们实际上在堆栈框架中生存”一样。我认为保留对象也可以做到这一点。没有人解释块是如何分配堆栈的。但是,评论确实链接到一篇文章 - cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html,它很好地解释了它。请参阅“块是有点奇怪的对象”。所以谢谢你!
  • 戴夫——我不太确定应该特别使用“非原子”。 (FWIW - 不一定正确!!! - 最新最伟大的 Apple doco 说你应该使用“复制” - 故事结束。)很难看出性能可能很重要,因为你在这里的帖子几乎是世界上唯一的参考这件事,也许它在那里是一件危险的事情。对这个晦涩的问题有什么想法吗?谢谢!
  • @JoeBlow 如果您担心同时从多个队列获取和设置属性的值,您只需要原子性。否则没关系。
  • 我/我们在任何地方都使用nonatomic。它应该是默认的 IMO。 atomic 导致更大的二进制文件,更低的性能(锁定所有访问器),并且它似乎承诺线程安全 - 通常必须在比属性访问器更高的级别上解决。
【解决方案2】:

或者,没有 typedef

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

【讨论】:

  • 为了澄清,由于语法非常不透明,这是一个名为“selectionHandler”的块属性,它接受一个 NSDictionary* 参数并返回 void。
  • 我不认为它很难阅读,但我同意使用 typedef 看起来更好。我倾向于为我通常要传递的参数编写一堆 typedef:PFObjectBlock、PFStringBlock、PFArrayBlock、PFErrorBlock 等。
  • id、SEL、IMP 是否允许进一步简化?
【解决方案3】:

你可以在 WWDC 2012 session 712 中找到一个很好的解释,从第 83 页开始。在 ARC 下保存块的正确方法如下:

@property(strong) my_block_type work;

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

self.work = nil;

【讨论】:

  • 仅适用于 ARC。在 MRC 下,这是错误的。但是copy 在 MRC 和 ARC 下都能正常工作
  • 我不认为副本在 MRC 中的所有情况下都能很好地工作,但也许在大多数情况下
  • 您对 MRC 的看法是对的,但它不在 ARC 中。抱歉,我想在之前的评论中说 ARC。
  • 真的很有趣,知道 ARC 如何设法将块移出堆栈吗?
  • "__block yourClass* blockSelf = self"。仅在“工作”属性中使用 blockSelf。
猜你喜欢
  • 2014-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 2019-12-29
  • 2011-07-14
  • 2013-01-07
  • 1970-01-01
相关资源
最近更新 更多