我正在将一些 Objective-C 代码转换为 ARC,它大量使用了 GCC "Statements and Declarations in Expressions" 扩展 ({})
。
GCC 扩展在预处理器宏中用于创建 Objective-C 对象。实际的宏相当复杂,所以这里是一个人为的例子来简化事情。就我的示例而言,假设_x
参数始终为NSString *
:
#define f(_x) ({ NSString *x = (_x); [NSString stringWithString: x]; })
这个宏当然会像这样调用:
void foo() { NSString *s = f(@"foo"); }
在 ARC 之前的环境中,这工作得很好。调用创建的对象stringWithString:
是一个自动释放的对象,GCC 扩展将它分配给s
.
NSLog()
在转换为 ARC(Xcode 4.4.1)之后,当语句块退出时,对象会立即释放(我通过实例化一个s it's的对象来确认这一点dealloc
)。
我尝试使用以下类型转换修改宏:
#define f(_x) ({ NSString *x = (_x); (__autoreleasing id) [NSString stringWithString: x]; })
和
#define f(_x) ({ NSString *x = (_x); (NSString __autoreleasing *) [NSString stringWithString: x]; })
但两种形式都会导致编译错误:
Explicit ownership qualifier on cast has no effect
看来 ARC 和这个 GCC 扩展是不兼容的。
是这样还是我错过了一些简单的告诉ARC不要立即释放对象的东西?
我确实有一些选择,目前最有吸引力的似乎是将所有这些宏转换为__inline__
函数,但我有相当多的代码要处理。我真的希望能快速修复,所以任何想法都会受到赞赏。