Ios 将对象作为弧下的不透明上下文参数安全传递

Ios 将对象作为弧下的不透明上下文参数安全传递,ios,cocoa,automatic-ref-counting,Ios,Cocoa,Automatic Ref Counting,在手动内存管理下,我经常使用这种模式: NSString * myStr = /* some local object */ [UIView beginAnimation:@"foo" context:(void *)[myStr retain]]; 然后,稍后以异步方式: - (void)animationDidStop:(NSString *)anim finished:(NSNumber *)num context:(void *)context { NSString * con

在手动内存管理下,我经常使用这种模式:

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];
}
i、 e.我手动管理用作不透明上下文的对象的生存期。(这适用于旧的UIView动画,也适用于我使用的其他类型的API。)

在ARC下,我的直觉是我想
\uuuu bridge\u retained
进入并
\uuuu bridge\u transfer
在处理程序中。但这将Cocoa对象视为
CFType
,并不是因为它是真正的桥接对象,而是为了将一个retain推入其喉部

这有效吗?这在风格上可以接受吗?如果没有,更好的解决方案是什么

(被接受的答案给出了一个不同的答案,说单独使用
\u bridge
是可以的,但在我看来这似乎是错误的,因为原始字符串一旦超出第一个函数的作用域,就有被释放的风险。对吗?)


*请不要说“改用基于块的动画”。(这不是我要问的。)

即使使用
\uuu bridge\u reserved
/
\uuu bridge\u transfer
对我来说似乎很好(将所有权转移到CoreFoundation或任何C代码或你自己身上都是一样的,你只需告诉ARC你在某个时候负责对象所有权,然后将所有权交还给ARC),您可以在用作
上下文的对象上保留一个
strong
引用,以便ARC不会回收其内存

这可以通过在类中使用
@属性(strong)
来实现,例如,当您以前执行
保留
时,将其影响为值,当您以前执行
释放
时,将其分配给
nil
,以释放字符串


请注意,如果需要在同一个类中保留多个上下文,可以选择使用
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

跟着你的直觉走<代码>\uuuuu bridge\u reserved
将对象的管理从ARC转移给您,而
\uuuuuu bridge\u transfer
则相反,不要担心将对象视为
CFType
-您实际上并没有这样做,只是接管了管理


您看到的另一种推荐方法是构造代码,以便ARC保留管理,但这很容易被认为是人为的(并且变得混乱)。让您正在使用的API保持其设计的值是干净的;只要在将管理交给API并返回给ARC的地方适当地注释代码。

将保留的对象作为
void*
上下文对象传递,一开始就很难看。如果你真的需要这样做,我不会担心它是否“在风格上可以接受”。在这种情况下,由于ARC强制进行某种类型的转换,你会希望使用简单的
\u桥
,对吗?谢谢。这是一个深思熟虑的选择,在某些情况下可能很有意义。这很有意义。从这个角度来看,似乎并不是你实际上保留了
CFType
,而是告诉ARC不要释放它。而当你在转回来的时候,你告诉ARC恢复所有权。这是一种更干净的思考方式。谢谢。事实上,看看llvm文档,我认为这确实保留并传输了对象。但我更高兴的是,从概念上来说,我不这么想。@BenZotto-更重要的是,对象没有被释放,而不是被保留;对象可能(但并非总是)已被保留,因此不需要额外的保留。