過了好久,今天終于有時間總結一下适配iPhone X相關的坑,總的來說有兩類坑,一個是導航欄+狀态欄的高度發生了變化,一個是一些沒有實作實作-tableView: viewForHeaderInSection:和-tableView: viewForFooterInSection:等代理方法的UITableView會出錯位的問題。
1. 判斷是否iPhone X:傳回YES或NO
1.1 判斷:宏
(1)依據螢幕分辨率
- 三目運算法
//是否iPhoneX YES:iPhoneX螢幕 NO:傳統螢幕
#define kIs_iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
- 多行邏輯判斷
//是否iPhoneX 1:iPhoneX螢幕 0:傳統螢幕
#define kIs_iPhoneX_test ({\
int tmp = 0;\
if ([UIScreen instancesRespondToSelector:@selector(currentMode)]) {\
if (CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size)) {\
tmp = 1;\
}else{\
tmp = 0;\
}\
}else{\
tmp = 0;\
}\
tmp;\
})
- 其中,反斜杠\并不是注釋或者其它的無用符号,其實是多行宏換行必須要用的标志。
- 最後一句tmp;\也是必須的,因為要将經過邏輯判斷得到的tmp作為該宏的傳回值。
(2)依據螢幕尺寸
#define kIs_iPhoneX (kSCREEN_WIDTH == 375.f && kSCREEN_HEIGHT == 812.f)
#define kSCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define kSCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
1.2 判斷:方法
- 方法:依據裝置型号
+(BOOL)getIs_iPhoneX{
struct utsname systemInfo;
uname(&systemInfo);
NSString *platform = [NSString stringWithCString: systemInfo.machine encoding:NSASCIIStringEncoding];
if([platform isEqualToString:@"iPhone10,3"]||[platform isEqualToString:@"iPhone10,6"]) {
return YES;
}else{
return NO;
}
}
2. 靈活傳回狀态欄+導航欄的高度
需求:靈活得到導航欄+狀态欄的高度,作為一個子視圖Y軸的起點。
- 宏定義
#define kStatusBarAndNavigationBarHeight (kIs_iPhoneX ? 88.f : 64.f)
- 調用範例
//自動适配
_segmentedControl.frame = CGRectMake(0, kStatusBarAndNavigationBarHeight, kSCREEN_WIDTH, 55);
3. 拓展:獲得iOS系統與App版本資訊
- 擷取iOS系統版本号:傳回字元串
+ (NSString *)getSystemVersion{
return [[UIDevice currentDevice] systemVersion];
}
- 擷取App版本号:傳回字元串
+ (NSString *)getAppVersion{
NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
// 擷取App的版本号
NSString *appVersion = [infoDic objectForKey:@"CFBundleShortVersionString"];
return appVersion;
}
4. 适配iPhone X的其他問題
适配iPhone X和Xcode 9的過程中,除了與導航欄相關的問題,還有一個問題經常出現,就是UITableView相關的問題。下面兩個辦法可以解決多數錯位的問題。
- VC建立tableView屬性的時候這樣設定
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
- 還可以這樣設定
//cell自适應高度
self.tableView.rowHeight = UITableViewAutomaticDimension;
//預估行高
self.tableView.estimatedRowHeight = 44.0f;
- 關于根視圖的安全區
iOS新增了個safeArea,原來的老代碼中,規定子視圖跟根子視圖的關系的代碼需要新增一個判斷:當iOS 11時,需要改為子視圖跟根子視圖的安全區的關系。這樣就不會在iPhone X的底部虛拟home有任何控件幹擾了。
if (@available(iOS 11.0, *)) {
make.edges.equalTo(self.view.safeAreaInsets)
} else {
make.edges.equalTo(self.view)
}
當然,一般除了tabbar不能放在這個底部虛拟home區,其它的視圖tableView視圖或者網頁視圖時可以放在底部虛拟home區中的。這時候,不需要強調必須把子視圖放在safeArea之内,原來的老代碼也就不用改。
君凱商聯網-iOS-字唐名僧