欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

ios宏定义学习

程序员文章站 2022-04-15 17:07:04
宏简介: 宏是一种批量处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串)。这种替换在预编译时进行,称作宏展开。编译器会在编译前扫描代码,如果遇到我们已经定义好的宏那么就会进行代码替换,宏只会在内存中co ......
宏简介:

宏是一种批量处理的称谓。一般说来,宏是一种规则或模式,或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串)。这种替换在预编译时进行,称作宏展开。编译器会在编译前扫描代码,如果遇到我们已经定义好的宏那么就会进行代码替换,宏只会在内存中copy一份,然后全局替换,宏一般分为对象宏和函数宏(下面会详细介绍)。

宏的弊端:

如果代码中大量的使用宏会是的编译时间变长。

对象宏:

像这样:#define m_pi 3.14159265358979323846264338327950288
这个没什么好讲的,我想只要是个ios程序员就都会用。
下面附送一波我们在工程中常用的宏

//获取屏幕的宽和高
#define screen_width   [uiscreen mainscreen].bounds.size.width
#define screenh_height [uiscreen mainscreen].bounds.size.height
//设置随机颜色
#define lrrandomcolor [uicolor colorwithred:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
//设置rgb和rgb颜色
#define lrrgbcolor(r, g, b) [uicolor colorwithred:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
#define lrrgbacolor(r, g, b, a) [uicolor colorwithred:(r)/255.0 green:(r)/255.0 blue:(r)/255.0 alpha:a]
// clear背景颜色
#define lrclearcolor [uicolor clearcolor]

//判断是否为iphone
#define is_iphone (ui_user_interface_idiom() == uiuserinterfaceidiomphone)
//判断是否为ipad
#define is_ipad (ui_user_interface_idiom() == uiuserinterfaceidiompad)
//判断是否为ipod
#define is_ipod ([[[uidevice currentdevice] model] isequaltostring:@"ipod touch"])
// 判断是否为 iphone 5se
#define iphone5se [[uiscreen mainscreen] bounds].size.width == 320.0f && [[uiscreen mainscreen] bounds].size.height == 568.0f
// 判断是否为iphone 6/6s
#define iphone6_6s [[uiscreen mainscreen] bounds].size.width == 375.0f && [[uiscreen mainscreen] bounds].size.height == 667.0f
// 判断是否为iphone 6plus/6splus
#define iphone6plus_6splus [[uiscreen mainscreen] bounds].size.width == 414.0f && [[uiscreen mainscreen] bounds].size.height == 736.0f
//获取系统版本
#define ios_system_version [[[uidevice currentdevice] systemversion] floatvalue]
//判断 ios 8 或更高的系统版本
#define ios_version_8_or_later (([[[uidevice currentdevice] systemversion] floatvalue] >=8.0)? (yes):(no))
//判断是真机还是模拟器
#if target_os_iphone
//iphone device
#endif
#if target_iphone_simulator
//iphone simulator
#endif

//沙盒目录文件
//获取temp
#define kpathtemp nstemporarydirectory()
//获取沙盒 document
#define kpathdocument [nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes) firstobject]
//获取沙盒 cache
#define kpathcache [nssearchpathfordirectoriesindomains(nscachesdirectory, nsuserdomainmask, yes) firstobject]

//nslog
#define nslog(format, ...) do {                                                                          \
    fprintf(stderr, "<%s : %d> %s\n",                                           \
    [[[nsstring stringwithutf8string:__file__] lastpathcomponent] utf8string],  \
    __line__, __func__);                                                        \
    (nslog)((format), ##__va_args__);                                           \
    fprintf(stderr, "-------\n");                                               \
} while (0)
函数宏:

其实说到宏那么不得不提的就是在宏中常用的预处理命令和运算符

指令及作用:

#空指令,无任何效果
#define定义宏
#undef取消已定义的宏
#if如果给定条件为真,则编译下面代码
#ifdef如果宏已经定义,则编译下面代码
#ifndef如果宏没有定义,则编译下面代码
#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif结束一个#if……#else条件编译块
#error停止编译并显示错误信息

#运算符:
例如: #define demo1(n) "123"#n
出现在宏定义中的#运算符把跟在其后的参数转换成一个字符串。有时把这种用法的#称为字符串化运算符

- (void)viewdidload {
    [super viewdidload];
    nslog(@"%s",demo1(abc));
}
//打印会输出 123abc

##运算符:
例如:#define demo2(m,n,j) m##n##j
##运算符用于把参数连接到一起。预处理程序把出现在##两侧的参数合并成一个符号

- (void)viewdidload {
    [super viewdidload];
    nslog(@"%d",demo2(1, 2, 3));
}
//打印会输出 123

举例:

//宏定义
#ifndef weakify
#define weakify(o) __weak typeof(o)  weak##o = o;
#define strongify(o) __strong typeof(o) o = weak##o;
#endif
//调用
-(void)demo2
{
    weakify(_v2)
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        nsinteger count =0;
        
        strongify(_v2)
        
        while( count<10) {
            
            count++;
            
            nslog(@"---------%@---%ld",weak_v2,(long)count);
            
            sleep(1);
            
        }
    });
    
    //3秒后将 self.v2对象 销毁
    dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(3*nsec_per_sec)),dispatch_get_main_queue(), ^{
        self.v2=nil;
    });
}
上面定义了两个宏,第一个相当于实现了__weak typeof(self) weakself = self;用##把weak和self连接起来,实现了self对block的弱引用,第二个宏的作用是保护block里的__weakself防止self被释放后block里的 __weakself也被释放(如果block在栈区,会将block copy一份到堆区,如果block在堆区,就在copy一份在堆区,此时block的引用计数为2)。
在上面demo2中_v2是当前类的属性,在并发队列线程的block中用strongify保护起来,在3秒后self.v2释放,但由于self.v2被copy一份到堆区,所以依然可以打印_v2。