ios宏定義學習

宏簡介:

宏是一種批量處理的稱謂。一般說來,宏是一種規則或模式,或稱語法替換 ,用于說明某一特定輸入(通常是字符串)如何根據預定義的規則轉換成對應的輸出(通常也是字符串)。這種替換在預編譯時進行,稱作宏展開。編譯器會在編譯前掃描代碼,如果遇到我們已經定義好的宏那么就會進行代碼替換,宏只會在內存中copy一份,然后全局替換,宏一般分為對象宏和函數宏(下面會詳細介紹)。

宏的弊端:

如果代碼中大量的使用宏會是的編譯時間變長。

對象宏:

像這樣:#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
//獲取狀態欄高度
#define Height_StatusBar            [[UIApplication sharedApplication] statusBarFrame].size.height
//導航欄加狀態欄高度
#define Height_NavBar               (Height_StatusBar >20?88.0f: 64.0f)
//獲取安全區高度
#define Height_SafeArea               (Height_StatusBar >20?34.0f: 0.00f)
//tabbar高度+SafeArea高度
#define Height_Tabbar               (Height_StatusBar >20? 83:49)
//設置隨機顏色
#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 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"])

//獲取系統版本
#define IOS_SYSTEM_VERSION [[[UIDevice currentDevice] systemVersion] floatValue]
//判斷 iOS 8 或更高的系統版本
#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)
函數宏:

其實說到宏那么不得不提的就是在宏中常用的預處理命令和運算符

指令及作用:

#空指令,無任何效果
#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。

block中不加strongify(_v2)

block中加strongify(_v2)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容