宏簡介:
宏是一種批量處理的稱謂南蓬。一般說來纺非,宏是一種規(guī)則或模式,或稱語法替換 赘方,用于說明某一特定輸入(通常是字符串)如何根據(jù)預定義的規(guī)則轉(zhuǎn)換成對應(yīng)的輸出(通常也是字符串)烧颖。這種替換在預編譯時進行,稱作宏展開窄陡。編譯器會在編譯前掃描代碼倒信,如果遇到我們已經(jīng)定義好的宏那么就會進行代碼替換,宏只會在內(nèi)存中copy一份泳梆,然后全局替換鳖悠,宏一般分為對象宏和函數(shù)宏(下面會詳細介紹)。
宏的弊端:
如果代碼中大量的使用宏會是的編譯時間變長优妙。
對象宏:
像這樣:#define M_PI 3.141592653
項目中常用的對象宏
//獲取iOS版本號
#define kIOSVersions [[[UIDevice currentDevice] systemVersion] floatValue]
//獲取window
#define kUIWindow [[[UIApplication sharedApplication] delegate] window] //獲得window
//獲取屏幕的寬和高
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREENH_HEIGHT [UIScreen mainScreen].bounds.size.height
//獲取狀態(tài)欄高度
#define Height_StatusBar [[UIApplication sharedApplication] statusBarFrame].size.height
//導航欄加狀態(tài)欄高度
#define Height_NavBar (Height_StatusBar >20?88.0f: 64.0f)
//獲取安全區(qū)高度
#define Height_SafeArea (Height_StatusBar >20?34.0f: 0.00f)
//tabbar高度+SafeArea高度
#define Height_Tabbar (Height_StatusBar >20? 83:49)
//設(shè)置隨機顏色
#define LRRandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
//設(shè)置RGB和RGB顏色
#define RGBColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
//16進制顏色
#define ColorWithHexValue(hexValue) [UIColor colorWithRed:((float)((hexValue & 0xFF0000) >> 16))/255.0 green:((float)((hexValue & 0xFF00) >> 8))/255.0 blue:((float)(hexValue & 0xFF))/255.0 alpha:1.0]
#define RGBAColor(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(r)/255.0 blue:(r)/255.0 alpha:a]
// clear背景顏色
#define ClearColor [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"])
//獲取系統(tǒng)版本
#define IOS_SYSTEM_VERSION [[[UIDevice currentDevice] systemVersion] floatValue]
//判斷 iOS 8 或更高的系統(tǒng)版本
#define IOS_VERSION_8_OR_LATER (([[[UIDevice currentDevice] systemVersion] floatValue] >=8.0)? (YES):(NO))
// 快速宏定義__weak
#define KWeakObj(weakName,objName) __weak typeof(&*objName) weakName = objName
// 快速宏定義__block
#define KBlockObj(blockName,objName) __block typeof(&*objName) blockName = objName
//判斷是真機還是模擬器
#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)
函數(shù)宏:
其實說到宏那么不得不提的就是在宏中常用的預處理命令和運算符
指令及作用:
#空指令乘综,無任何效果
#define定義宏
#undef取消已定義的宏
#if如果給定條件為真,則編譯下面代碼
#ifdef如果宏已經(jīng)定義套硼,則編譯下面代碼
#ifndef如果宏沒有定義卡辰,則編譯下面代碼
#elif如果前面的#if給定條件不為真,當前條件為真邪意,則編譯下面代碼
#endif結(jié)束一個#if……#else條件編譯塊
#error停止編譯并顯示錯誤信息
#運算符:
例如: #define demo1(n) "123"#n
出現(xiàn)在宏定義中的#運算符把跟在其后的參數(shù)轉(zhuǎn)換成一個字符串九妈。有時把這種用法的#稱為字符串化運算符
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%s",demo1(abc));
}
//打印會輸出 123abc
##運算符:
例如:#define demo2(m,n,j) m##n##j
##運算符用于把參數(shù)連接到一起。預處理程序把出現(xiàn)在##兩側(cè)的參數(shù)合并成一個符號
- (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
//調(diào)用
-(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;
});
}
上面定義了兩個宏雾鬼,第一個相當于實現(xiàn)了__weak typeof(self) weakself = self;
用##把weak和self連接起來萌朱,實現(xiàn)了self對block的弱引用,第二個宏的作用是保護block里的__weakself防止self被釋放后block里的 __weakself也被釋放(如果block在棧區(qū)策菜,會將block copy一份到堆區(qū)晶疼,如果block在堆區(qū),就在copy一份在堆區(qū)又憨,此時block的引用計數(shù)為2)翠霍。
在上面demo2中_v2是當前類的屬性,在并發(fā)隊列線程的block中用strongify保護起來蠢莺,在3秒后self.v2釋放寒匙,但由于self.v2被copy一份到堆區(qū),所以依然可以打印_v2躏将。