天天看點

iOS 開發·适配iPhone X相關的宏和方法

過了好久,今天終于有時間總結一下适配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-字唐名僧