做个记录,方便自己查看
条件编译只能决定编译阶段代码是否编译,并不能决定运行时的逻辑,还需要结合具体系统版本判断
if (@available(iOS 12.0, *)) {
code...
}
- 条件编译知识点
1、#if的使用说明
#if的后面接的是表达式
#if (MAX==10)||(MAX==20)
code...
#endif
它的作用是:如果(MAX==10)||(MAX==20)成立,那么编译器就会把其中的#if 与 #endif之间的代码编译进去(注意:是编译进去,不是执行!!)
#if defined的使用
#if后面接的是一个宏。
2、#if defined (x)
code...
#endif
这个#if defined它不管里面的“x”的逻辑是“真”还是“假”它只管这个程序的前面的宏定义里面有没有定义“x”这个宏,如果定义了x这个宏,那么,编译器会编译中间的…code…否则不直接忽视中间的…code…代码。
另外 #if defined(x)也可以取反,也就用 #if !defined(x)
3、#ifdef的使用
#ifdef的使用和#if defined()的用法一致
#ifndef又和#if !defined()的用法一致。
最后强调两点:
第一:这几个宏定义只是决定代码块是否被编译!
第二:别忘了#endif
4、#ifndef 的使用
#ifndef _XXXX
code...
#else
code...
#endif
5、使用案例
//可以通过逻辑与判断多个条件
#if defined(DEBUG) && DEBUG
@property (nonatomic, weak) id<FLAnimatedImageViewDebugDelegate> debug_delegate;
#endif
//判断单个条件
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
//嵌套使用
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
// 条件编译分支 #elif
// 以下示例中的条件编译语句假定一个名为 DLEVEL 的之前定义的符号常量。
#if DLEVEL > 5
#define SIGNAL 1
#if STACKUSE == 1
#define STACK 200
#else
#define STACK 100
#endif
#else
#define SIGNAL 0
#if STACKUSE == 1
#define STACK 100
#else
#define STACK 50
#endif
#endif
#if DLEVEL == 0
#define STACK 0
#elif DLEVEL == 1
#define STACK 100
#elif DLEVEL > 5
display( debugptr );
#else
#define STACK 200
#endif
- iOS 开发环境SDK版本宏定义
//具体路径为: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/Availability.h
#define __IPHONE_2_0 20000
#define __IPHONE_2_1 20100
#define __IPHONE_2_2 20200
#define __IPHONE_3_0 30000
#define __IPHONE_3_1 30100
#define __IPHONE_3_2 30200
#define __IPHONE_4_0 40000
#define __IPHONE_4_1 40100
#define __IPHONE_4_2 40200
#define __IPHONE_4_3 40300
#define __IPHONE_5_0 50000
#define __IPHONE_5_1 50100
#define __IPHONE_6_0 60000
#define __IPHONE_6_1 60100
#define __IPHONE_7_0 70000
#define __IPHONE_7_1 70100
#define __IPHONE_8_0 80000
#define __IPHONE_8_1 80100
#define __IPHONE_8_2 80200
#define __IPHONE_8_3 80300
#define __IPHONE_8_4 80400
#define __IPHONE_9_0 90000
#define __IPHONE_9_1 90100
#define __IPHONE_9_2 90200
#define __IPHONE_9_3 90300
#define __IPHONE_10_0 100000
#define __IPHONE_10_1 100100
#define __IPHONE_10_2 100200
#define __IPHONE_10_3 100300
#define __IPHONE_11_0 110000
#define __IPHONE_11_1 110100
#define __IPHONE_11_2 110200
#define __IPHONE_11_3 110300
#define __IPHONE_11_4 110400
#define __IPHONE_12_0 120000
#define __IPHONE_12_1 120100
#define __IPHONE_12_2 120200
///这些系统版本宏。如果在比较低的sdk 中是没有定义的,这时可以直接使用数字
__IPHONE_OS_VERSION_MAX_ALLOWED 这个宏得到的是当前开发环境的系统SDK版本
__IPHONE_OS_VERSION_MIN_REQUIRED 这个宏它是当前项目选择的最低支持的版本
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// 在 iOS10.0 及以上的开发环境 编译此部分代码
#else
// 在低于 iOS10.0 的开发环境 编译此部分代码
#endif
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0
// 如果选择(iOS Deployment Target)的最低支持版本在iOS8.0及以上才可以使用
- (void)execute;
#endif
///判断真机或者模拟器
TARGET_IPHONE_SIMULATOR 或 TARGET_OS_IPHONE 来区分
#if TARGET_OS_IPHONE
NSLog(@"真机");
self.ijkPlayer = [[CHPIJKPlayerManager alloc] init];
self.playerController = [CHPlayerController playerWithPlayerManager:self.ijkPlayer containerView:self.playerFahterView];
[self.playerController setControlView:self.controlView];
self.playerController.assetURL = [NSURL URLWithString:TestUrl];
[self.controlView showTitle:@"我是标题" coverImage:[UIImage new]];
#else
NSLog(@"模拟器");
#endif
- 头文件处理
//iOS 11.0 以上的SDK编译,跟下面的代码等价
#ifdef __IPHONE_11_0
#import <ReplayKit/ReplayKit.h>
#endif
#if defined(__IPHONE_11_0)
#import <ReplayKit/ReplayKit.h>
#endif
- 属性处理
#if defined(__IPHONE_12_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0)
@property (nonatomic, strong) RPSystemBroadcastPickerView *broadPickerView API_AVAILABLE(ios(12.0));
#endif
#endif
- 代码块处理
//示例一:
- (UICollectionViewFlowLayout *)flowLayout {
if (!_flowLayout) {
_flowLayout = [[UICollectionViewFlowLayout alloc] init];
_flowLayout.minimumInteritemSpacing = 0;
_flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
if (self.outside) {
_flowLayout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);
}else {
#ifdef __IPHONE_11_0
if (@available(iOS 11.0, *)) {
#else
if ((NO)) {
#endif
_flowLayout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);
}else {
_flowLayout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);
}
}
}
return _flowLayout;
}
//示例二:
- (void)startSystemRecording:(UIViewController *)inVC {
if (!inVC) {
return;
}
#if defined(__IPHONE_12_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0)
if (@available(iOS 12.0, *)) { //加判断是为了消除警告
_broadPickerView = [[RPSystemBroadcastPickerView alloc] initWithFrame:CGRectMake(200, 200, 60, 60)];
_broadPickerView.preferredExtension = BrocastExtension;
_broadPickerView.showsMicrophoneButton = NO;
[_broadPickerView setBackgroundColor:[UIColor orangeColor]];
[inVC.view addSubview:_broadPickerView];
}
#else
NSString *appname = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:appname message:@"开启系统界面录制,请先到控制中心->长按录制按钮开启" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[alert addAction:ok];
[inVC presentViewController:alert animated:YES completion:nil];
#endif
}
头文件的导入判断
#if __has_include(<SDWebImage/UIImageView+WebCache.h>)
#import <SDWebImage/UIImageView+WebCache.h>
#else
#import "UIImageView+WebCache.h"
#endif
参考博客
#if、#elif、#else 和 #endif 指令详解 (C/C++)
条件编译 -- TARGET_OS_IPHONE