iOS thoughtful articles | macro definition

I. Introduction

Acer is processed in batch and title, it is simply to replace certain text according to defined rules. Replacement process in the program compile time, and thus extensive use of the macro will result in compile time longer; and the type of security check replacement process is not carried out; also need to pay attention to the "edge effect";

For example #define N 1 + 2, when used NSInteger a = N / 2, the expected 1.5result is 2, because the conversion is in process NSInteger a = 1 + 2 / 2, it is proposed to add brackets indicate that when using a macro as a whole.

Want to know if the macro must first look at the source, OC evolved from the C language, naturally inherited the fine tradition of the C language, here briefly, C language preprocessor , which includes three aspects:

  1. Macro definition: #define directive defines a macro, # undef command to delete a macro definition.
  2. File contains: #include command specifies a content of the document is included in the program.
  3. Conditional compilation: # if, # ifdef, # ifndef, # elif, # else and #endif instructions may be a section of text comprising the conditional compiler program to be tested or excluded from the program.

Note that pre-orders are the symbol "#" at the beginning.

1.1 Macro classification

Most of the macro is divided into objects by type macros and macro functions, but also by incoming parameters are divided into macro and macro without parameters parameters.

1.1.1 Macro objects
#define STATUS_HEIGHT 20
1.1.2 Macro Functions
#define MAX(X, Y)  ((X) > (Y) ? (X) : (Y))

The difference between 1.1 macros and constants defined

#defineAnd constit can be used to modify constants.

  • Different compilers treatment
      define the macro is expanded in a pretreatment stage.
      const constants are compiled using the operational phase.
  • Different types of security checks and
      define the type of macro is not, do not do any type checking, just start.
      const constants have specific types, will perform at compile time type checking.
  • Different Memories
      define macros just launched, how many places, how many times had begun, does not allocate memory. (Macro definition does not allocate memory, variable definition allocates memory.)
      Const constants will be allocated in memory (can be a heap may also be a stack).
  • const can save space and avoid unnecessary memory allocation.
  • Improved efficiency; ordinary compiler normally not constant const allocated storage space, but they are stored in the symbol table, which makes it a constant during compilation, storage and no memory read operation, such that its efficiency high.
  • Macro replacement only for replacement, not calculation, not an expression solving;

Some 1.2 macro usage

1.2.1 character of

Convert incoming single-character to character parameter name, a reference to a pair of single quotes.

#define STRING @#s    // 's'
1.2.2 stringified

Before adding a macro parameter #, then expand the macro body when the macro parameters will be expanded to a string.

#define NSSTRING #str  // "str"
1.2.3 connection

If the macro identifiers body where there are ##, then the macro body when extended, the macro parameters are replaced directly to the identifier.

#define COMMAND(PREFIX, NAME)  PREFIX##NAME  
1.2.4 Wrap

Experience required wrap can be used \ number for the connection;

#define PRINT_IF(CONDITION) \
do { if (CONDITION) \
NSLog(@"print hello"); } \
while (0)
1.2.5 macro varying parameter ( and _VA_ARGS)

The following are examples of OC custom Log:

#ifdef DEBUG
#define Log(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define Log(...)
#endif

Note that:
__VA_ARGS__: pass at least one parameter
##__VA_ARGS__: just pass a few parameters

Two. C language macros

Here are some C language macro:

#define        定义一个预处理宏
#undef         取消宏的定义
#include       包含文件命令
#include_next  与#include相似, 但它有着特殊的用途
#if            编译预处理中的条件命令, 相当于C语法中的if语句
#ifdef         判断某个宏是否被定义, 若已定义, 执行随后的语句
#ifndef        与#ifdef相反, 判断某个宏是否未被定义
#elif          若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if
#else          与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
#endif         #if, #ifdef, #ifndef这些条件命令的结束标志.
#defined       与#if, #elif配合使用, 判断某个宏是否被定义
#line          标志该语句所在的行号
#              将宏参数替代为以参数值为内容的字符窜常量
##             将两个相邻的标记(token)连接为一个单独的标记
#pragma        说明编译器信息
#warning       显示编译警告信息
#error         显示编译错误信息

Is not feeling very familiar, even in iOS development is also frequently used contents.
In addition to the basic operation of the macro there are predefined macros, predefined macros to facilitate the processing of some useful information, which defines a number of pre-identifier, i.e. predefined macros. Name-defined macros are scheduled to "_ " (two underscores) the beginning and end, if the macro name consists of two words, then the middle order " " (an underscore) to connect. And, in general by the macro name in uppercase characters.
The following are common predefined macros:

Macros description
FUNTION Get the current function name
DATE Hack front of the mouth for compiling a source file, with "Mmm dd yyy" represents a constant string of the form
FILE The current name of the source file, expressed as a string constant
LINE The current source line number of the sense element, represented by a decimal integer constant, which can change over instruction #line
TIME The latest compilation inch between the current source file, use "hh: mm: ss" form of representation rather string constants
STDC If for compiling conforms to ISO standards before today, then the macro value of 1, otherwise undefined
COUNTER No repeat of the counter, the program starts from the beginning of each call will ++, macros defined in common language without duplicate parameter names
func Where the scope of the function name, common in the log

III. OC related to macro expansion

3.1 system-related macros

Macros description
__has_include It used to check whether a file is introduced
NS_ASSUME_NONNULL_BEGIN & NS_ASSUME_NONNULL_END Macro code between these two, all simple pointers are assumed to be objects nonnull
__cplusplus C is the identification code or codes c ++
__has_feature(objc_arc) Determine whether the ARC, otherwise MRC
@available(iOS 11, *) It meets the needs of current iOS11
TARGET_IPHONE_SIMULATOR When the condition is satisfied, the simulator code is executed; otherwise, execution code is non simulator
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0 The system equipment is greater than 8.0 or the code
NS_REQUIRES_SUPER Shen Mingzai category If you override this method, you must call the parent class method
FOUNDATION_EXPORT Used to define the constant, upon detection of direct comparison pointer values ​​are equal, the efficiency is relatively fast
NS_AVAILABLE_IOS(8_0) This method can be used in iOS3.0 and later versions, if you call this method in older than version 5.0, it will lead to the collapse
NS_DEPRECATED_IOS(2_0, 6_0) This method introduced in iOS2.0, 6.0 is deleted
NS_AVAILABLE(10_8, 6_0) This macro tells us that this method separately with Mac OS 10.8 and iOS 6.0 was introduced
NS_DEPRECATED(10_0, 10_6, 2_0, 4_0) This method with Mac OS 10.0 and iOS 2.0 is introduced, after being discarded and Mac OS 10.6 iOS 4.0
NS_CLASS_AVAILABLE(10_11, 9_0) This class with Mac OS 10.11, respectively, and are introduced iOS9.0
NS_ENUM_AVAILABLE(10_11, 9_0) This enumeration with Mac OS 10.11, respectively, and iOS9.0 are introduced
__IPHONE_OS_VERSION_MAX_ALLOWED Allowing maximum iOS version
__IPHONE_OS_VERSION_MIN_ALLOWED Minimum version of iOS

3.2 custom macros

/**** UI尺寸 ****/
//获取屏幕宽度与高度
#define SCREEN_WIDTH   [UIScreen mainScreen].bounds.size.width
#define SCREENH_HEIGHT [UIScreen mainScreen].bounds.size.height
//根据6,7,8适配
#define ScaleWidth(width) (width / 375.0) * SCREEN_WIDTH
#define ScaleHeight(height) (height / 667.0) * SCREENH_HEIGHT
//是否是iPhoneX
#define k1IS_iPhoneX (SCREEN_WIDTH == 375.f && SCREENH_HEIGHT == 812.f)
#define k2IS_iPhoneX  ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)

//判断是否为X系列
#define IPHONE_X \
({BOOL isPhoneX = NO;\
if (@available(iOS 11.0, *)) {\
isPhoneX = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0;\
}\

// 状态栏高度
#define kStatusBarHeight        (IPHONE_X ? 44.f : 20.f)
// 顶部导航栏高度
#define kNavigationBarHeight    44.f
// 顶部安全距离
#define kSafeAreaTopHeight      (IPHONE_X ? 88.f : 64.f)
// 底部安全距离
#define kSafeAreaBottomHeight   (IPHONE_X ? 34.f : 0.f)
// Tabbar高度
#define kTabbarHeight           49.f
// 去除上下导航栏剩余中间视图高度
#define ContentHeight           (kScreenHeight - kSafeAreaTopHeight - kSafeAreaBottomHeight - kTabbarHeight)


/**** 颜色 ****/
//随机颜色
#define ZBRandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
//RGB
#define ZBRGBColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
//RGBA
#define ZBRGBAColor(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(r)/255.0 blue:(r)/255.0 alpha:a]
//十六进制颜色
#define ZBRGBHex(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
//十六进制颜色,透明度
#define ZBRGBHexAlpha(rgbValue,a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:(a)]

/**** 系统相关 ****/
//app版本号
#define DEVICE_APP_VERSION      (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]
//app Build版本号
#define DEVICE_APP_BUILD        (NSString *)[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]
//系统版本号(string)
#define DEVICE_OS_VERSION       [[UIDevice currentDevice] systemVersion]
//系统版本号(float)
#define DEVICE_OS_VERSION_VALUE [DEVICE_OS_VERSION floatValue]
//检测是否是竖屏状态
#define IsPortrait ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait || [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)

/**** 沙盒目录文件 ****/
//temp
#define ZBPathTemp NSTemporaryDirectory()
//Document
#define ZBPathDocument [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
//Cache
#define ZBPathCache [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]

/**** 数据判空 ****/
//字符串是否为空
#define kStringIsEmpty(str) ([str isKindOfClass:[NSNull class]] || str == nil || [str length] < 1 ? YES : NO )
//数组是否为空
#define kArrayIsEmpty(array) (array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0)
//字典是否为空
#define kDictIsEmpty(dic) (dic == nil || [dic isKindOfClass:[NSNull class]] || dic.allKeys == 0)
//是否是空对象
#define kObjectIsEmpty(_object) (_object == nil \
|| [_object isKindOfClass:[NSNull class]] \
|| ([_object respondsToSelector:@selector(length)] && [(NSData *)_object length] == 0) \
|| ([_object respondsToSelector:@selector(count)] && [(NSArray *)_object count] == 0))

/**** 常用缩写 ****/
#define kApplication            [UIApplication sharedApplication]
#define kKeyWindow              [UIApplication sharedApplication].keyWindow
#define kAppDelegate            [UIApplication sharedApplication].delegate
#define kUserDefaults           [NSUserDefaults standardUserDefaults]
#define kNotifCenter            [NSNotificationCenter defaultCenter]

/**** 其他 ****/
//弱引用
#define ZBWeak __weak typeof(self) weakSelf = self;
#define ZBWeakSelf(type)  __weak typeof(type) weak##type = type;
//强引用
#define ZBStrongSelf(type) __strong typeof(type) type = weak##type;

//角度转换弧度
#define ZBDegreesToRadian(x) (M_PI * (x) / 180.0)
//弧度转换角度
#define ZBRadianToDegrees(radian) (radian*180.0)/(M_PI)

//block判空回调
#define ZBBlockNotEmpt(block, ...)  if (block) { block(__VA_ARGS__); }

//.h头文件中的单例宏
#define ZBSingletonH(name) + (instancetype)shared##name;

//.m文件中的单例宏
#define ZBSingletonM(name) \
static id _instance;\
+ (instancetype)allocWithZone:(struct _NSZone *)zone{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
+ (instancetype)shared##name{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [[self alloc] init];\
});\
return _instance;\
}\
- (id)copyWithZone:(NSZone *)zone{\
return _instance;\
}

IV. Summary

Introduced so many macro-related knowledge, few thoughts on the macro concluded under:

  1. Macros directly call the method name or the name of the constants is easy to understand, it can reduce duplication of code, standardized, easy to modify;
  2. When you use too long to compile macros will increase, and the need to pay attention to the "edge effect" to prevent unexpected errors occur;
  3. Define the macro should comply with norms, such as no space between the macro name and parentheses parameters; the definition of the expression to the outside parentheses parcels;

So much for being the first, follow-up will continue to update, and finally welcome bigwigs under the Chit-Chat.

Learn:

GCC Macros

Macro - from entry to the master

[How to use const, static, extern right] | Those who chase dry goods

const constant define the difference between macro definition

Macro definition of black magic - Macro rookie off Manual

Appreciated C language preprocessor conditional compilation and execution process

Several pit and special use of C language macro definition

C language is used in macro definitions

In-depth understanding of the macro C language definition

Reproduced in: https: //www.jianshu.com/p/0d434c2de2ae

Guess you like

Origin blog.csdn.net/weixin_33834679/article/details/91231281