iOS开发---宏定义浅析
2019-06-19 本文已影响0人
Cary_Xu
磨刀不误砍柴工。
工欲善其事必先利其器。
首先,宏定义只是文本替换!一篇功能全面、语法清晰、准确无误的宏定义可以让你的编程过程如虎添翼。
一、宏定义的优点
1、重用性高,维护方便
2、提高程序的运行效率
3、提升编程的灵活性,增强代码可读性
二、宏定义的缺点
宏定义属于“预处理命令”的一种,在提高程序的运行效率的同时,并不会检测参数的合法性,存在安全隐患。
三、宏定义的定义型式
#define 表示符 字符串
例:
#define kSystemVersion [[UIDevice currentDevice] systemVersion]
#define 宏名(参数列表) 字符串
例:
#define kColorRGBA(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:a]
四、宏定义为什么常用"k"为前缀
偶然看到这样一个解释,记录一下,以便知其然知其所以然!
It is a general programming notation not specific to Objective-C (i.e. Hungarian Notation) and the "k" stands for "constant".
『这是一个通用编程符号,不是Objective-C特有的(即匈牙利符号),“k”代表“常数”。』
五、常用宏定义
1.自定义NSLog
//NSLog
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s:%s\nLine:%d\n%s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String],__func__,__LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(FORMAT, ...) nil
#endif
//Log for print Rect, Size, Point
#define kShowRect(rect) NSLog(@" rect.x = %f\n rect.y = %f\n rect.w = %f\n rect.h = %f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)
#define kShowSize(size) NSLog(@" size.w = %f\n size.h = %f", size.width, size.height)
#define kShowPoint(point) NSLog(@" point.x = %f\n point.y = %f", point.x, point.y)
2.屏幕尺寸
#define kScreenSize \
([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)] \
? CGSizeMake([UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale,[UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale) \
: [UIScreen mainScreen].bounds.size)
//Screen_Width
#define kScreenWidth kScreenSize.width
//Screen_Height
#define kScreenHeight kScreenSize.height
//Screen_Size_Current
#define kScreenCurrent [[UIScreen mainScreen] currentMode].size
这里补充一个小知识,宏定义中要执行换行操作就在行末使用""断行
3.系统版本
//Version_System
#define kSystemVersion [[UIDevice currentDevice] systemVersion]
#define kSystemVersionDouble [[[UIDevice currentDevice] systemVersion] doubleValue]
//APP版本号
#define kAppVersion [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleShortVersionString"]
//当前版本 = 版本v
#define K_IS_SYSTEM_VERSION_EQUAL_TO(v) ([[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
//当前版本 > 版本v
#define K_IS_SYSTEM_VERSION_MORE_THAN(v) ([[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
//当前版本 < 版本v
#define K_IS_SYSTEM_VERSION_LESS_THAN(v) ([[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
4.系统对象
//APP对象 (单例对象)
#define kApplication [UIApplication sharedApplication]
//主窗口 (keyWindow)
#define kKeyWindow [UIApplication sharedApplication].keyWindow
//APP对象的delegate
#define kAppDelegate [UIApplication sharedApplication].delegate
//NSUserDefaults实例化
#define kUserDefaults [NSUserDefaults standardUserDefaults]
5.通知中心
//通知中心 (单例对象)
#define kNotificationCenter [NSNotificationCenter defaultCenter]
//发送通知
#define kPostNotification(name,obj,info) [[NSNotificationCenter defaultCenter] postNotificationName:name object:obj userInfo:info]
//移除通知
#define kRemoveNotification(_self,name) ([[NSNotificationCenter defaultCenter] removeObserver:_self name:name object:nil])
//移除所有通知
#define kRemoveAllNotification(_self) ([[NSNotificationCenter defaultCenter] removeObserver:_self])
6.沙盒路径
//获取沙盒 temp
#define kPathTemp NSTemporaryDirectory()
//获取沙盒 Document
#define kPathDocument [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
//获取沙盒 Cache
#define kPathCache [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]
//Library/Caches 文件路径
#define kFilePath ([[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil])
7.时间相关
//获得当前的年份
#define kCurrentYear [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:[NSDate date]]
//获得当前的月份
#define kCurrentMonth [[NSCalendar currentCalendar] component:NSCalendarUnitMonth fromDate:[NSDate date]]
//获得当前的日期
#define kCurrentDay [[NSCalendar currentCalendar] component:NSCalendarUnitDay fromDate:[NSDate date]]
//获得当前的小时
#define kCurrentHour [[NSCalendar currentCalendar] component:NSCalendarUnitHour fromDate:[NSDate date]]
//获得当前的分
#define kCurrentMin [[NSCalendar currentCalendar] component:NSCalendarUnitMinute fromDate:[NSDate date]]
//获得当前的秒
#define kCurrentSec [[NSCalendar currentCalendar] component:NSCalendarUnitSecond fromDate:[NSDate date]]
//Time
#define kTimeMinute 60
#define kTimeHour (kTimeMinute * 60)
#define kTimeDay (kTimeHour * 24)
#define kTimeFiveDay (kTimeDay * 5)
#define kTimeWeek (kTimeDay * 7)
#define kTimeMonth (kTimeDay * 30.5)
#define kTimeYear (kTimeDay * 365)
8.设备类型
//Version_Idiom
#define K_IS_PAD ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
#define K_IS_PHONE ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
#define kSystemIdiom (([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) ? @"ipad": @"iphone")
//iPhone_type
#define K_IS_RETINA ([[UIScreen mainScreen] scale] == 2.0f)
#define K_IS_INSTANCES [UIScreen instancesRespondToSelector:@selector(currentMode)]
#define K_IS_iPhone4 (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(640, 960)) : NO)
#define K_IS_iPhone5 (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(640, 1136)) : NO)
#define K_IS_iPhone6 (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(750, 1334)) : NO)
#define K_IS_iPhone6Plus (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(1242, 2208)) : NO)
#define K_IS_iPhone_X (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(1125, 2436)) : NO)
#define K_IS_iPhone_Xr (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(828, 1792)) : NO)
#define K_IS_iPhone_Xs (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(1125, 2436)) : NO)
#define K_IS_iPhone_Xs_Max (K_IS_INSTANCES ? K_IS_PHONE && CGSizeEqualToSize(kScreenCurrent,CGSizeMake(1242, 2688)) : NO)
#define K_IS_iPhoneXXX (K_IS_iPhone_X || K_IS_iPhone_Xr || K_IS_iPhone_Xs || K_IS_iPhone_Xs_Max)
9.常用常数
//在 iPhoneX 系列上Bottom Bar的安全增量
#define kHeightSafeBottom (K_IS_iPhoneXXX ? 34.0 : 0)
//在 iPhoneX 系列上Status Bar的安全增量
#define kHeightSafeStatus (K_IS_iPhoneXXX ? 24.0 : 0)
//系统手势增量
#define kHeightGestureSystem (K_IS_iPhoneXXX ? 13.0 : 0)
//状态栏高度
#define kHeightStatusBar (20.0 + kHeightSafeStatus)
//导航栏高度
#define kHeightNavBar 44.0
//顶部高度
#define kHeightTop (kHeightStatusBar + kHeightNavBar)
//底部tabBar高度
#define kHeightTabBar (49 + kHeightSafeBottom)
10.Frame相关
//View 坐标(x,y)、宽高(width,height)、左上角坐标(minX,minY)、中心坐标(midX,midY)、右下角坐标(maxX,maxY)
#define kFrameX(v) (v).frame.origin.x
#define kFrameY(v) (v).frame.origin.y
#define kFrameWidth(v) (v).frame.size.width
#define kFrameHeight(v) (v).frame.size.height
#define kFrameMinX(v) CGRectGetMinX((v).frame)
#define kFrameMinY(v) CGRectGetMinY((v).frame)
#define kFrameMidX(v) CGRectGetMidX((v).frame)
#define kFrameMidY(v) CGRectGetMidY((v).frame)
#define kFrameMaxX(v) CGRectGetMaxX((v).frame)
#define kFrameMaxY(v) CGRectGetMaxY((v).frame)
11.常见判空
//字符串是否为空
#define K_IS_NULL_String(str) (str == nil || [str isKindOfClass:[NSNull class]] || [str length] < 1)
//数组是否为空
#define K_IS_NULL_Array(array) (array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0 || [array isEqual:[NSNull null]])
//字典是否为空
#define K_IS_NULL_Dict(dic) (dic == nil || [dic isKindOfClass:[NSNull class]] || dic.allKeys == 0 || [dic isEqual:[NSNull null]])
//是否是空对象
#define K_IS_NULL_Object(_object) (_object == nil \
|| [_object isKindOfClass:[NSNull class]] \
|| ([_object respondsToSelector:@selector(length)] && [(NSData *)_object length] == 0) \
|| ([_object respondsToSelector:@selector(count)] && [(NSArray *)_object count] == 0))
//判断对象是否为空,为空则返回默认值
#define kGetDefaultWhenNullObject(_value,_default) ((_value == nil \
|| !_value \
|| [_value isKindOfClass:[NSNull class]] \
|| [_value isEqualToString:@"(null)"] \
|| [_value isEqualToString:@"<null>"] \
|| [_value isEqualToString:@""] \
|| [_value length] == 0) ? _default : _value)
12.常用工具
//Color_RGBA
#define kColorRGBA(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:a]
//Color_RGB
#define kColorRGB(r, g, b) kColorRGBA(r, g, b, 1.0)
//Color_Random
#define kColorRandom kColorRGB(arc4random_uniform(256),arc4random_uniform(256),arc4random_uniform(256))
//Color_Value
#define kColorValue(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 16))/255.0 blue:((float)((rgbValue & 0xFF) >> 16))/255.0 alpha:1.0];
//Fount
#define kFont(x) [UIFont systemFontOfSize:x]
//加载图片
#define kGetImage(imageName) [UIImage imageNamed:[NSString stringWithFormat:@"%@",imageName]]
//加载本地图片
#define kGetImageWithFile(name,ext)\
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:(name) ofType:(ext)]]
//加载xib
#define kLoadNib(nibName) [UINib nibWithNibName:nibName bundle:[NSBundle mainBundle]]
//字符串拼接
#define kStringFormat(FORMAT,...) \
[NSString stringWithFormat:FORMAT,##__VA_ARGS__]
//由角度转换为弧度
#define kDegreesToRadian(d) (M_PI * (d) / 180.0)
//由弧度转换为角度
#define kRadianToDegrees(r) (r * 180.0) / (M_PI)
//UIAlertView
#define kUIAlertView(FORMAT, ...) \
[[[UIAlertView alloc] initWithTitle:@"提示" message:[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil] show]
13.非常用工具
//带自动提示的keypath宏
#define keypath2(OBJ, PATH) \
(((void)(NO && ((void)OBJ.PATH, NO)), # PATH))
//根据当前 view 找所在tableview 里的 indexpath
#define kIndexpathSubviewTable(subview,tableview)\
({\
CGRect subviewFrame = [subview convertRect:subview.bounds toView:tableview];\
NSIndexPath *tabIndexPath = [tableview indexPathForRowAtPoint:subviewFrame.origin];\
tabIndexPath;\
})\
//根据当前view 找所在collectionview 里的 indexpath
#define kIndexpathSubviewCollection(subview,collectionview)\
({\
CGRect subviewFrame = [subview convertRect:subview.bounds toView:collectionview];\
NSIndexPath *tabIndexPath = [collectionview indexPathForItemAtPoint:subviewFrame.origin];\
tabIndexPath;\
})\
//根据当前view 找所在tableview 里的 tableviewcell
#define kCellSubviewTable(subview,tableview)\
({\
CGRect subviewFrame = [subview convertRect:subview.bounds toView:tableview];\
NSIndexPath *indexPath = [tableview indexPathForRowAtPoint:subviewFrame.origin];\
UITableViewCell *tabCell = [tableview cellForRowAtIndexPath:indexPath];\
tabCell;\
})\
14.未完待续
不定时补充......
有错误的地方欢迎指出!
六、总结
最后,引用《C陷阱与缺陷》的一句话对其进行总结:
宏并不是函数,宏并不是语句,宏并不是类型定义。