web-dev-qa-db-ja.com

__bridgeとCFBridgingRelease / CFBridgingRetainをいつ使用する必要がありますか?

「__bridge」を使用して色のIDをキャストする次のコードがあります。

  CGColorRef tabColor = (5 == 5
                         ? [UIColor blueColor].CGColor
                         : [UIColor greenColor].CGColor);

  CGColorRef startColor = [UIColor whiteColor].CGColor;
  CGColorRef endColor   = tabColor;
  NSArray    *colors    = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil];

  CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

しかし、次のようになります。

  NSArray    *colors    = [NSArray arrayWithObjects:(id)CFBridgingRelease(startColor), (id)CFBridgingRelease(endColor), nil];

  CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)CFBridgingRetain(colors), locations);

より良い解決策になりますか?

18
Andrew Arrow

CoreFoundationオブジェクトstartColorendColorは、名前に「Create」または「Copy」が含まれる関数によって返されないため、「所有」しません(比較 「CoreFoundationのメモリ管理プログラミングガイド」の「作成ルール」 また、オブジェクトを所有していないため、CFBridgingRelease()を使用してARCに「所有権を譲渡」してはなりません。

_[NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil];
_

正しい。そして

_CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
_

なぜなら

_CGGradientCreateWithColors(colorSpace, (CFArrayRef)CFBridgingRetain(colors), locations);
_

(+1)保持された配列をCGGradientCreateWithColors()に渡します。この関数はcolors引数を解放しないため、これはメモリリークになります。

22
Martin R

NSURLでも同じ問題です

NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"sound" ofType:@"wav"];
NSURL *soundURL = [NSURL fileURLWithPath:soundPath];
AudioServicesCreateSystemSoundID(CFBridgingRetain(soundURL), &soundEffect);
0
oscarr