在手动内存管理,我用这种模式相当频繁:
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
单是好的,但在我看来,是错误的,因为原始的字符串会在被尽快释放风险的,因为它超出范围在第一功能,对吧?)
*请不要说“使用基于块的动画,而不是”。 (这不是我要问一下。)
去与你的直觉。 __bridge_retained
从ARC的目的是你的转账管理,同时__bridge_transfer
做相反的工作,不用担心治疗的对象作为CFType
-你不是真的这样做,只是接手管理。
你看到推荐的另一种方法是建立你的代码,以便ARC保留管理,但是这很容易遇到的做作(和变得混乱)。 在您使用维护的价值,因为它是专门做的API是干净的; 适当只是注释代码,其中管理交给API,并返回到ARC。
即使使用__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