传递对象下ARC安全不透明的上下文参数(Passing objects safely as opaq

2019-09-23 20:17发布

在手动内存管理,我用这种模式相当频繁:

NSString * myStr = /* some local object */
[UIView beginAnimation:@"foo" context:(void *)[myStr retain]];

然后,后来和异步:

- (void)animationDidStop:(NSString *)anim finished:(NSNumber *)num context:(void *)context
{
    NSString * contextStr = (NSString *)context;
    // ...
    [contextStr release];
}

即我手动管理用作不透明上下文对象的寿命。 (这是旧的UIView动画也为其他类型的API的,我用正确的。)

根据ARC,我的直觉是,我想__bridge_retained进入和__bridge_transfer在处理程序, 这里建议 。 但是,这把可可的对象作为CFType并不是因为它真的桥接,但只是推搡一个保留了它的喉咙的目的。

这是有效的,这是可以接受的文体? 如果不是,有什么更好的解决方案*?

(接受的答案对这个问题给出了不同的答案,说__bridge单是好的,但在我看来,是错误的,因为原始的字符串会在被尽快释放风险的,因为它超出范围在第一功能,对吧?)

*请不要说“使用基于块的动画,而不是”。 (这不是我要问一下。)

Answer 1:

去与你的直觉。 __bridge_retained从ARC的目的是你的转账管理,同时__bridge_transfer做相反的工作,不用担心治疗的对象作为CFType -你不是真的这样做,只是接手管理。

你看到推荐的另一种方法是建立你的代码,以便ARC保留管理,但是这很容易遇到的做作(和变得混乱)。 在您使用维护的价值,因为它是专门做的API是干净的; 适当只是注释代码,其中管理交给API,并返回到ARC。



Answer 2:

即使使用__bridge_retained / __bridge_transfer似乎没什么问题(将所有权转移给的CoreFoundation或任何C代码,或者自己是完全一样的,你就告诉ARC,你有责任在某一点上物体的所有权,并给予所有权稍后电弧),可以改为保持一个strong ,你作为你使用你的对象引用context ,如果某个地方你喜欢,让ARC不会回收它的内存。

这可以通过使用来实现@property(strong)在你的类为例,它影响到的价值,当你做之前你retain并将其分配到nil的时候,你以前没有你的release ,让串去。


请注意,如果你需要多个环境保持周围在同一个班级,你可以选择使用一个选项NSMutableArray ,让您的上下文字符串代替左右宣布为每个上下文的属性。

@interface YourClass ()
@property(strong) NSMutableArray* runningAnimationContexts;
@end

@implementation YourClass
-(id)init {
  self = [super init];
  if (self) {
    self.runningAnimationContexts = [NSMutableArray array];
  }
  return self;
}

-(void)someMethod
{
  // Example with two different parallel animations using old API

  NSString * myStr = /* some local object */
  [self.runningAnimationContexts addObject:myStr]; // ~ retain
  [UIView beginAnimation:@"foo" context:(__bridge)myStr];
  ...
  [UIView commitAnimations];

  NSString * myStr2 = /* some other local object */
  [self.runningAnimationContexts addObject:myStr2]; // ~ retain
  [UIView beginAnimation:@"foo2" context:(__bridge)myStr2];
  ...
  [UIView commitAnimations];

}
- (void)animationDidStop:(NSString *)anim finished:(NSNumber *)num context:(void *)context
{
  NSString * contextStr = (__bridge NSString *)context;
  // ...
  [self.runningAnimationContexts removeObject:contextStr]; // ~ release
}
@end


文章来源: Passing objects safely as opaque context params under ARC