判斷系統(tǒng)
- 描述
判斷系統(tǒng)
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
#endif
#if os(Linux)
#endif
targetEnvironment(simulator)
- 描述
判斷是否為模擬器 - 用法
#if targetEnvironment(simulator)
// 模擬器
#else
#endif
__has_include
- 描述
此宏傳入一個(gè)你想引入文件的名稱作為參數(shù),如果該文件能夠被引入則返回1,否則返回0。 - 用法
#if __has_include(<AFNetworking/AFNetworking.h>)
#import <AFNetworking/AFNetworking.h>
#else
#import "AFNetworking.h"
#endif
__func__,__FUNCTION__ ,__PRETTY_FUNCTION__
- 描述
GCC實(shí)現(xiàn)了如下的函數(shù)宏
__func__ C99的標(biāo)準(zhǔn),但是GCC只輸出函數(shù)名稱。
__FUNCTION__ 同__func__
,
__PRETTY_FUNCTION__ 非標(biāo)準(zhǔn)宏。這個(gè)宏比__FUNCTION__
功能更強(qiáng):
(1)若用 g++ 編譯 C++ 程序,__FUNCTION__
只能輸出類的成員函數(shù)名,不會(huì)輸出類名;而__PRETTY_FUNCTION__
則會(huì)以<return-type> <class-name>::<member-function-name>(<parameters-list>)
的格式輸出成員函數(shù)的詳悉信息(注: 只會(huì)輸出 parameters-list 的形參類型,而不會(huì)輸出形參名)。
(2) 若用 gcc 編譯 C 程序,__PRETTY_FUNCTION__
跟__FUNCTION__
的功能相同.
__VA_ARGS__
- 描述
C99 編譯器標(biāo)準(zhǔn)允許定義可變參數(shù)宏(variadic macros),這樣就使用擁有可以變化的參數(shù)表的宏。
#define FYFLog(format, ...) NSLog(format, __VA_ARGS__)
缺省號(hào)代表一個(gè)可以變化的參數(shù)表。使用保留名 '__VA_ARGS__' 把參數(shù)傳遞給宏。當(dāng)宏的調(diào)用展開時(shí),實(shí)際的參數(shù)就傳遞給 NSLog() 了。
"##"
- 描述
(1)在標(biāo)準(zhǔn) C 里,你不能省略可變參數(shù),但是你卻可以給它傳遞一個(gè)空的參數(shù)。GNU CPP 在這種情況下可以讓你完全的忽略可變參數(shù)。在上面的例子中,編譯器仍然會(huì)有問題( complain ),因?yàn)楹暾归_后,里面的字符串后面會(huì)有個(gè)多余的逗號(hào)。
為了解決這個(gè)問題, CPP 使用一個(gè)特殊的‘ ## ’操作。書寫格式為:
#define FYFLog(format, ...) NSLog(format, ##__VA_ARGS__)
這里,如果可變參數(shù)被忽略或?yàn)榭眨?## ’操作將使預(yù)處理器( preprocessor )去除掉它前面的那個(gè)逗號(hào)。如果你在宏調(diào)用時(shí),確實(shí)提供了一些可變參數(shù), GNU CPP 也會(huì)工作正常,它會(huì)把這些可變參數(shù)放到逗號(hào)的后面。
(2)##還可以起到連接的作用
#define FYFName(Item) Item##Name
NSString *numName;
NSLog(@"%@", FYFName(num));
這里將會(huì)輸出 numName 的數(shù)據(jù).
__LINE__
- 描述:在源代碼中插入當(dāng)前源代碼行號(hào)
- 用法:
#ifdef DEBUG
#define FYFLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define FYFLog(...)
#endif
__FILE__
- 描述:在源文件中插入當(dāng)前源文件名
- 用法:
NSLog(@"__FILE__ %s", __FILE__);
__DATE__
- 描述:在源文件中插入當(dāng)前的編譯日期
__TIME__
- 描述 在源文件中插入當(dāng)前編譯時(shí)間
__STDC__
- 描述:當(dāng)要求程序嚴(yán)格遵循ANSI C標(biāo)準(zhǔn)時(shí)該標(biāo)識(shí)被賦值為1
__cplusplus
- 描述:當(dāng)編寫 C++ 程序時(shí)該標(biāo)識(shí)符被定義
NS_ASSUME_NONNULL_BEGIN 與 NS_ASSUME_NONNULL_END
- 描述:
在swift中,可以使用 !
和 ?
來表示一個(gè)對(duì)象是 optional
,還是 non-optional
,如 view?
和 view!
。而在 Objective-C 中則沒有這一區(qū)分,view 即可表示這個(gè)對(duì)象是 optional
,也可表示是non-optioanl。這樣就會(huì)造成一個(gè)問題:在 Swift 與 Objective-C 混編時(shí),Swift 編譯器并不知道一個(gè) Objective-C 對(duì)象到底是 optional
還是 non-optional
,因此這種情況下編譯器會(huì)隱式地將 Objective-C 的對(duì)象當(dāng)成是non-optional
。
為了解決這個(gè)問題,蘋果在 Xcode 6.3 引入了一個(gè) Objective-C 的新特性:nullability annotations
。這一新特性的核心是兩個(gè)新的類型注釋:__nullable
和 __nonnull
。從字面上我們可以猜到,__nullable
表示對(duì)象可以是 NULL
或 nil
,而 __nonnull
表示對(duì)象不應(yīng)該為空。當(dāng)我們不遵循這一規(guī)則時(shí),編譯器就會(huì)給出警告。
事實(shí)上,在任何可以使用 const
關(guān)鍵字的地方都可以使用 __nullable
和 __nonnull
,不過這兩個(gè)關(guān)鍵字僅限于使用在指針類型上。而在方法的聲明中,我們還可以使用不帶下劃線的 nullable
和 nonnull
。
** Nonnull 區(qū)域設(shè)置 (Audited Regions
) **
如果需要每個(gè)屬性或每個(gè)方法都去指定 nonnull
和 nullable
,是一件非常繁瑣的事。蘋果為了減輕我們的工作量,專門提供了兩個(gè)宏:NS_ASSUME_NONNULL_BEGIN
和 NS_ASSUME_NONNULL_END
。在這兩個(gè)宏之間的代碼,所有簡單指針對(duì)象都被假定為 nonnull
,因此我們只需要去指定那些 nullable
的指針。
不過,為了安全起見,蘋果還制定了幾條規(guī)則:
typedef
定義的類型的nullability
特性通常依賴于上下文,即使是在Audited Regions
中,也不能假定它為nonnull
。- 復(fù)雜的指針類型(如
id *
)必須顯示去指定是nonnull
還是nullable
。例如,指定一個(gè)指向nullable
對(duì)象的nonnull
指針,可以使用__nullable id * __nonnull
。- 我們經(jīng)常使用的
NSError **
通常是被假定為一個(gè)指向nullable NSError
對(duì)象的nullable
指針。
__IPHONE_OS_VERSION_MAX_ALLOWED 與 __IPHONE_OS_VERSION_MIN_REQUIRED
描述:
這兩個(gè)宏定義(預(yù)編譯宏),
__IPHONE_OS_VERSION_MAX_ALLOWED
滿足要求的系統(tǒng)最高版本(可以理解為當(dāng)前設(shè)備的系統(tǒng)版本)
__IPHONE_OS_VERSION_MIN_REQUIRED
滿足要求的系統(tǒng)最低版本(也就是iOS Deployment Target選擇的版本)用法:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
// 系統(tǒng)版本在iOS7.0及以上則編譯此部分代碼
#else
// 如果低于iOS7.0則編譯此部分代碼
#endif
NS_EXTENSION_UNAVAILABLE_IOS
- 描述:
標(biāo)記 iOS 插件不能使用這些 API,后面有一個(gè)參數(shù),可以作為提示(比如提示應(yīng)該用什么 API 替換)。 - 用法:
// 示例 1:
NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.")
@interface AFNetworkActivityIndicatorManager : NSObject
@end
// 示例 2:
+ (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.");