Objective-C 宏定义

2016-03-15  本文已影响666人  spectatorNan

1. 判断设备

// 是否高清屏  
#define isRetina ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO)  
// 是否模拟器  
#define isSimulator (NSNotFound != [[[UIDevice currentDevice] model] rangeOfString:@"Simulator"].location)  
// 是否iPad  
#define isPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)  
// 是否iPad  
#define someThing (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)? ipad: iphone  

2. 基本的使用

//定义π值 3.1415926    
#define PI 3.1415926     
//则在程序用可以如下使用       
double i=2*PI*3;     
//效果相当于  double i=2*3.1415926*3;    
  
//预处理命令可以定义任何符合格式的形式,例如判断年份是否闰年  
#define  IS_LEAP_YEAR  year%4==0&&year%100!=0||year%400==0    
//使用时则可以直接    
if(IS_LEAP_YEAR)    
   
//或者可以定义一个参数      
#define  IS_LEAP_YEAR(y)  y%4==0&&y%100!=0||y%400==0    
//使用时则可以直接     
int ys=2012;     
if(IS_LEAP_YEAR(ys))       
    
//通常预处理程序定义在一行 如果好分行 比如说太长需要换行  需要使用“/”符号 表示还有下一行,多行分列也是如此,例:    
#Define  IS_LEAP_YEAR  year%4==0&&year%100!=0/    
           ||year%400==0     
//宏定义参数后边放一个# 那么在调用该宏时,预处理程序将根据宏参数创建C风格的常量字符串 例:    
#define STR(x) # x    
//将会使得 随后调用的      
  
NSLOG(STR(Programming in Objective-c./n));    
//显示结果为 Programming in Objective-c./n  

3. 关于#与##的操作符

    #define WARN_IF(EXPR)\  
do {\  
if (EXPR)\  
fprintf(stderr, "Warning: " #EXPR "\n");\  
} while(0)  
  
上面代码中的反斜线\主要用来转译换行符,即屏蔽换行符。  
  
那么如下的代码调用:  
WARN_IF(divider == 0);  
  
将被解析为:  
do {\  
if (divider == 0)\  
fprintf(stderr, "Warning: " "divider == 0" "\n");\  
} while(0);  
#define LINK_MULTIPLE(a, b, c, d) a##_##b##_##c##_##d  
typedef struct _record_type LINK_MULTIPLE(name, company, position, salary);  
/*  
* 上面的代码将被替换为  
* typedef struct _record_type name_company_position_salary;  
*/  
  
又如下面的例子:  
#define PARSER(N) printf("token" #N " = %d\n", token##N)  
  
int token64 = 64;  
  
如下调用宏:  
PARSER(64);  
  
将被解析为:  
printf("token" "64" " = %d\n", token64);  
  
在obj-c中,如果我有如下定义:  
#define _X(A, B) (A#B)  
#define _XX(A, B) _X([NSString stringWithFormat:@"%@_c", A], B)  
gcc将报错!  
正确的写法为:  
#define _XX(A, B) _X(([NSString stringWithFormat:@"%@_c", A]), B)  

4. 宏定义 Objective-C 单例

#define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_)  
static _object_name_ *z##_shared_obj_name_ = nil;   
+ (_object_name_ *)_shared_obj_name_ {              
@synchronized(self) {                             
if (z##_shared_obj_name_ == nil) {              
/* Note that ‘self’ may not be the same as _object_name_ */                                
/* first assignment done in allocWithZone but we must reassign in case init fails */       
z##_shared_obj_name_ = [[self alloc] init];                                                
_GTMDevAssert((z##_shared_obj_name_ != nil), @”didn’t catch singleton allocation”);        
}                                               
}                                                 
return z##_shared_obj_name_;                      
}                                                   
  
+ (id)allocWithZone:(NSZone *)zone {                
@synchronized(self) {                             
if (z##_shared_obj_name_ == nil) {              
z##_shared_obj_name_ = [super allocWithZone:zone];  
return z##_shared_obj_name_;                  
}                                               
}                                                 
   
/* We can’t return the shared instance, because it’s been init’d */  
_GTMDevAssert(NO, @”use the singleton API, not alloc+init”);         
return nil;                                       
}                                                   
  
- (id)retain {                                      
return self;                                      
}                                                   
  
- (NSUInteger)retainCount {                         
return NSUIntegerMax;                             
}                                                   
  
- (void)release {                                   
}                                                   
  
- (id)autorelease {                                 
return self;                                      
}                                                   
  
- (id)copyWithZone:(NSZone *)zone {                 
return self;                                      
}
    ```

### 5. 条件编译
```ObjC
#if !defined(FCDebug) || FCDebug == 0  
#define FCLOG(...) do {} while (0)  
#define FCLOGINFO(...) do {} while (0)  
#define FCLOGERROR(...) do {} while (0)  
     
#elif FCDebug == 1  
#define FCLOG(...) NSLog(__VA_ARGS__)  
#define FCLOGERROR(...) NSLog(__VA_ARGS__)  
#define FCLOGINFO(...) do {} while (0)  
     
#elif FCDebug > 1  
#define FCLOG(...) NSLog(__VA_ARGS__)  
#define FCLOGERROR(...) NSLog(__VA_ARGS__)  
#define FCLOGINFO(...) NSLog(__VA_ARGS__)  
#endif  
    ```

### 6. 参照C语言的预处理命令简介:

define 定义一个预处理宏

undef 取消宏的定义

include 包含文件命令

include_next 与#include相似, 但它有着特殊的用途

if 编译预处理中的条件命令, 相当于C语法中的if语句

ifdef 判断某个宏是否被定义, 若已定义, 执行随后的语句

ifndef 与#ifdef相反, 判断某个宏是否未被定义

elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if

else 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else

endif #if, #ifdef, #ifndef这些条件命令的结束标志.

defined 与#if, #elif配合使用, 判断某个宏是否被定义

line 标志该语句所在的行号

将宏参数替代为以参数值为内容的字符窜常量

将两个相邻的标记(token)连接为一个单独的标记

pragma 说明编译器信息#warning 显示编译警告信息

error 显示编译错误信息

参考链接:http://www.uml.org.cn/c++/200902104.asp
上一篇下一篇

猜你喜欢

热点阅读