Objective-C宏来检测变量是否是原始的

Jef*_*mas 13 objective-c objective-c-runtime

我正在寻找一个宏来检测变量是Objective-C中的对象还是原语.

在这种情况下,我知道参数必须是一个变量,永远不会是一个表达式.

这是我提出的最好的事情:

#define IS_OBJECT(x)    ( @encode(__typeof__(x))[0] == '@' )
#define IS_PRIMITIVE(x) ( !IS_OBJECT(x) )
Run Code Online (Sandbox Code Playgroud)

用法:

NSString *testString = @"test";
NSString *nilString = nil;
NSInteger testInteger = 1;

STAssertTrue(IS_OBJECT(testString), @"IS_OBJECT(testString) must be YES");
STAssertTrue(IS_OBJECT(nilString), @"IS_OBJECT(nilString) must be YES");
STAssertFalse(IS_OBJECT(testInteger), @"IS_OBJECT(testInteger) must be NO");
Run Code Online (Sandbox Code Playgroud)

肯定有更好的办法.


更新

考虑到@ChrisDevereux评论,我更新了IS_OBJECT宏.

#define IS_OBJECT(x) ( strchr("@#", @encode(__typeof__(x))[0]) != NULL )
Run Code Online (Sandbox Code Playgroud)

它现在通过:

NSString *testString = @"test";
NSString *nilString = nil;
NSInteger testInteger = 1;
Class classTest = [NSString class];

STAssertTrue(IS_OBJECT(testString), @"IS_OBJECT(testString) must be YES");
STAssertTrue(IS_OBJECT(nilString), @"IS_OBJECT(nilString) must be YES");
STAssertFalse(IS_OBJECT(testInteger), @"IS_OBJECT(testInteger) must be NO");
STAssertTrue(IS_OBJECT(classTest), @"IS_OBJECT(classTest) must be YES");
Run Code Online (Sandbox Code Playgroud)

我仍然不喜欢这个答案,并希望有一些更光滑的东西.运行时库中有什么东西可以做到这一点吗?

Nik*_*uhe 7

这是使用C11的通用选择机制的另一种方式._Generic是标准(现代)C并且在clang中支持一段时间.

#define IS_OBJECT(T) _Generic( (T), id: YES, default: NO)
Run Code Online (Sandbox Code Playgroud)

感觉运行时间对我来说有点少,所以我更喜欢它@encode.但说实话,我只是用它来做这个答案,因为我喜欢_Generic给宏的功能,并认为更多的人应该开始使用它.如果您不了解它,您应该阅读上面链接的Robert Gamble的文章.

  • 我只是说我希望人们写更多的预处理器魔术吗?恢复!恢复! (4认同)