【问题标题】:Objective-C Preprocessor Definition, Dynamic C-String to NSString DeclarationObjective-C 预处理器定义,动态 C-String 到 NSString 声明
【发布时间】:2012-06-06 19:46:27
【问题描述】:

我正在尝试创建一个宏定义,它可以根据上下文发出 C++ 或 Objective-C,但似乎无法轻松地在宏内构造 NSString。 C++ 版本很简单,因为它使用常规字符串,但要制作一个发出 NSString 的字符串却很棘手:

#define FOO(x) bar(@##x)

预期的结果是通过前缀@将字符串参数转换为NSString参数:

FOO("x")
// => bar(@"x")

我得到的是一个阻止编译的错误:

Pasting formed '@"x"', an invalid preprocessing token

【问题讨论】:

    标签: c++ objective-c c-preprocessor


    【解决方案1】:
    NSString *x = @"text";
    

    等于:

    NSString *x = CFSTR("text");
    

    PS NSString* 和 CFStringRef 和 __CFString* 以及 NSCFStringRef 都是一样的:Toll-Free Bridged Types

    【讨论】:

    • CFSTR 很有希望,但它是CFStringRef 而不是NSString*
    • @tadman 他们是一回事,而且是免费桥接的。
    • 我在尝试这个时得到“不兼容的指针类型将'CFStringRef'(又名const struct __CFString *)传递给NSString*类型的参数”。
    • @tadman 您可以将CFSTR 转换为NSString*,它是toll-free bridged
    • 有效的定义:#define AS_NSSTRING(x) ((NSString*)CFSTR(x))
    【解决方案2】:

    您不能使用## 连接元素,除非它们一起形成有效的预处理标记,但您可以调用NSString 的构造函数,该构造函数采用C 字符串,如下所示:

    #define FOO(x) [NSString stringWithUTF8String:(x)]
    

    【讨论】:

    • 那是不是以后必须解除分配的东西,不像@"..."是静态的,对吧?
    • @tadman 这会产生一个自动释放的字符串,除非你保留它,否则你不拥有它。
    • 应该改为stringWithUTF8String:
    【解决方案3】:

    嗯,为什么不这样:

    #define FOO(x) bar(@x)
    

    ?

    无需进行令牌粘贴或字符串化或任何奇怪的事情。您只希望替换点的参数列表中的内容前面有一个 @ 符号。所以就这样做吧。

    【讨论】:

    • 仅当 x 在引号中时才有效。有时这是不可取的。例如:#define CASE_TO_NAME(x) case x: return (NSString*) CFSTR(x); break 然后是一个 switch 语句 switch (val) { CASE_TO_NAME(foo); CASE_TO_NAME(bar); // etc. }
    • 当然,但这不是问题所在。而且您的示例将中断,因为它不会在CFSTR(x) 中对x 进行字符串化。
    • 当您更改为CFSTR(#x) 时,我的示例是固定的,这应该很明显。 (为什么我不能编辑我的评论?!)
    猜你喜欢
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 2010-11-10
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多