我在Objective-C中包装某个C API。我有一个方便的方法,从过程API中获取一些CFTypeRef
并从OOP API返回一个包装对象。此对象保留传递的CFTypeRef
并在其自己的释放时释放它。便利方法如下所示:
+ (id) wrapFoo: (CFTypeRef) foo;
我有很多方法只需要获取一些CFTypeRef
并返回包装对象:
- (id) doSomething {
CFTypeRef foo = CFCreateSomeObject();
id wrapper = [WrappingClass wrapFoo:foo];
CFRelease(foo);
return wrapper;
}
这有点笨拙,所以我提出了另一种方便的方法:
+ (id) wrapNonRetainedFoo: (CFTypeRef) foo {
id wrapper = [self wrapFoo:foo]; // CFRetains foo
CFRelease(foo);
return wrapper;
}
现在我可以像这样重写doSomething
方法:
- (id) doSomething {
return [WrappingClass wrapNonRetainedFoo:CFCreateSomeObject()]; // XXX
}
我喜欢这个。我并不为wrapNonRetainedFoo
方法感到自豪,但它不是包的公共接口的一部分,并且在几种方法中省去了几行样板代码。
缺点是静态分析器将XXX
行标记为潜在泄漏。我能做得更好吗?我尝试使用cf_consumed
参数属性来玩,让分析器知道我稍后会释放该对象,但它似乎不起作用。
答案 0 :(得分:2)
1)Apple使用的分析仪版本仍然不支持AFAIK cf_consumed。
2)我注意到如果你使wrapNonRetainedFoo
实例方法警告将神秘地消失。但由于wrap...
最好是一个类方法,这对我们没用。
3)我能想到的唯一解决方案就是这个丑陋的宏(不是用于制作,而是作为概念的证明):
#define WRAP_CFTYPE(klass, valExpr) ({ CFTypeRef val = valExpr; id result = [klass wrap:val]; CFRelease(val); result; })
用法:
WrappingClass *wrapper = WRAP_CFTYPE(WrappingClass, CFArrayCreate(NULL, NULL, 0, NULL))