平常我們開發(fā)中不可避免用到一些宏,特此記錄下咒劲。
一、自己常常寫的宏
尺寸宏
// 寬和高基本都是用的
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
// navigationBar 默認(rèn)的高度
#define NAVIGATIONBAR_HEIGHT 64
// tabBar 默認(rèn)的高度
#define UITABBAR_HEIGHT 49
顏色宏
// RGB顏色轉(zhuǎn)換(16進(jìn)制->10進(jìn)制)
#define UICOLOR_HEX(hexString) [UIColor colorWithRed:((float)((hexString & 0xFF0000) >> 16))/255.0 green:((float)((hexString & 0xFF00) >> 8))/255.0 blue:((float)(hexString & 0xFF))/255.0 alpha:1.0]
// 帶有RGBA的顏色設(shè)置
#define UICOLOR_RGB(R, G, B, A) [UIColor colorWithRed:R/255.0 green:G/255.0 blue:B/255.0 alpha:A]
// 隨機(jī)顏色
#define UICOLOR_RANDOM [UIColor colorWithRed:(arc4random()%255)/255.0 green:(arc4random()%255)/255.0 blue:(arc4random()%255)/255.0 alpha:1.0]
打印宏
// 直接替換
#ifdef DEBUG
#define NSLog(...) NSLog(__VA_ARGS__)
#define debugMethod() NSLog(@"%s", __func__)
#else
#define NSLog(...)
#define debugMethod()
#endif
真機(jī)還是模擬器
#if TARGET_OS_IPHONE
//iPhone Device
#endif
#if TARGET_IPHONE_SIMULATOR
//iPhone Simulator
#endif
\ 行繼續(xù)操作符
#define DEFINE_SINGLETON_FOR_CLASS(className) \
\
+ (className *)sharedManager { \
static className *shared##className = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
@synchronized(self){ \
shared##className = [[self alloc] init]; \
} \
}); \
return shared##className; \
}
系統(tǒng)宏
//獲取系統(tǒng)版本
#define IOS_VERSION [[[UIDevice currentDevice] systemVersion] floatValue]
// 大于 iOS 8 的系統(tǒng)
#define ABOVE_IOS8 (([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) ? YES : NO)
// 直接判斷機(jī)型
#define IS_IPHONE_4 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)480) < DBL_EPSILON)
#define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)667) < DBL_EPSILON)
#define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)736) < DBL_EPSILON)
目錄宏
// Directory 目錄
#define PATH_DIRECTORY [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
// Cache 目錄
#define PATH_CACHE [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
// 數(shù)據(jù)庫 目錄
#define PATH_DATABASE_CACHE [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0]
weakify & strongify
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif
區(qū)分不同版本的文字寬度處理
PS: MBProgressHUD 獲取
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
#define MB_TEXTSIZE(text, font) [text length] > 0 ? [text \
sizeWithAttributes:@{NSFontAttributeName:font}] : CGSizeZero;
#else
#define MB_TEXTSIZE(text, font) [text length] > 0 ? [text sizeWithFont:font] : CGSizeZero;
#endif
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
#define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \
boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin) \
attributes:@{NSFontAttributeName:font} context:nil].size : CGSizeZero;
#else
#define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \
sizeWithFont:font constrainedToSize:maxSize lineBreakMode:mode] : CGSizeZero;
#endif
某些場景的宏
例如 KVO 中的那個(gè) KeyPath, 有時(shí)我們直接輸入诫隅,并不好輸入腐魂,而且容易輸入錯(cuò)誤,沒有提示逐纬。
這樣寫后蛔屹,直接有提示,而且方便豁生。
#define PQ_KEY_PATH(objc,keyPath) @(((void)objc.keyPath,#keyPath))
PQ_KEY_PATH(self.tableView, contentOffset);
同時(shí)兔毒,我們要注意在 Swift 中已經(jīng)沒有宏啦,為什么會沒有呢甸箱?不可否認(rèn)的是宏定義很可能隱藏很多 bug育叁,這對于開發(fā)其實(shí)并不是一件好事。所以我們在使用的時(shí)候必須注意芍殖,具體可以看看喵神的宏定義的黑魔法 - 宏菜鳥起飛手冊豪嗽。
二、自帶的宏
// 獲取兩者之間小的
#define MIN(A,B) ((A) < (B) ? (A) : (B))
// 獲取兩者之間大的
#define MAX(A,B) ((A) > (B) ? (A) : (B))
// 絕對值
#define ABS(A) ((A) < 0 ? (-(A)) : (A))
//CGFLOAT_MAX 無窮大
//CGFLOAT_MIN 無窮接近0
#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
# define CGFLOAT_IS_DOUBLE 1
# define CGFLOAT_MIN DBL_MIN
# define CGFLOAT_MAX DBL_MAX
#else
# define CGFLOAT_TYPE float
# define CGFLOAT_IS_DOUBLE 0
# define CGFLOAT_MIN FLT_MIN
# define CGFLOAT_MAX FLT_MAX
#endif
// 這三個(gè)倒是用的不多
#define NSIntegerMax LONG_MAX
#define NSIntegerMin LONG_MIN
#define NSUIntegerMax ULONG_MAX
// UIKIT_EXTERN extern
#ifdef __cplusplus
#define UIKIT_EXTERN extern "C" __attribute__((visibility ("default")))
#else
#define UIKIT_EXTERN extern __attribute__((visibility ("default")))
#endif
NS_CLASS_AVAILABLE_IOS(7_0)
NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.");
相對來說豌骏,這塊自身提供其實(shí)可以是常用的龟梦。特別是MIN
,MAX
肯适,CGFLOAT_MIN
都是常常用到的变秦。
三、用于判斷或注釋的
#define 定義一個(gè)預(yù)處理宏
#undef 取消宏的定義
#if 編譯預(yù)處理中的條件命令框舔, 相當(dāng)于C語法中的if語句
#ifdef 判斷某個(gè)宏是否被定義(#define過)蹦玫, 若已定義, 執(zhí)行隨后的語句
#ifndef 與#ifdef相反刘绣, 判斷某個(gè)宏是否未被定義
#elif 若#if樱溉, #ifdef, #ifndef或前面的#elif條件不滿足纬凤, 則執(zhí)行#elif之后的語句福贞, 相當(dāng)于C語法中的else-if
#else 與#if, #ifdef停士, #ifndef對應(yīng)挖帘, 若這些條件不滿足完丽, 則執(zhí)行#else之后的語句, 相當(dāng)于C語法中的else
#endif #if拇舀, #ifdef逻族, #ifndef這些條件命令的結(jié)束標(biāo)志.
defined 與#if, #elif配合使用骄崩, 判斷某個(gè)宏是否被定義
#ifdef PQ_MAX
// 如果定義了宏P(guān)Q_MAX聘鳞,則編譯此處的代碼
#else
// 如果沒有定義宏P(guān)Q_MAX,則編譯此處的代碼
#endif
#ifndef PQ_MAX
// 如果沒有定義宏P(guān)Q_MAX要拂,則編譯此處的代碼
#elif PQ_MAX_INT
// 如果定義了宏P(guān)Q_MAX,同時(shí)還定義了宏P(guān)Q_MAX_INT抠璃,則編譯此處的代碼
#else
// 定義了宏P(guān)Q_MAX,但是沒有定義宏P(guān)Q_MAX_INT,則編譯此處的代碼
#endif
#pragma 說明編譯器信息
#warning 顯示編譯警告信息
#error 顯示編譯錯(cuò)誤信息