天天看点

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-字唐名僧