iOS小技能:UITableView的适配 (iOS10/iOS14/iOS16.0)

语言: CN / TW / HK

本文正在参加「金石计划」

引言

如果按照开发规范写代码,不会存在关于UITableView的适配问题。

  • 如果按照规范使用UITableViewHeaderFooterView,就不会存在iOS16横竖屏切换场景的页脚问题。
  • 如果按照规范添加UITableViewCell的子试图到UITableViewCellContentView,就不会存在iOS14被遮挡的问题。
  • 如果将tableView:viewForFooterInSection: 和tableView:heightForFooterInSection:方法都注释掉,就不会存在iOS10即使heightForFooterInSection高度返回0 也会显示视图的问题。

I iOS16.0 横竖屏切换适配

调用完转屏方法以后,view需要重新更新frame

1.1 获取当前屏幕横竖屏状态

  • (UIInterfaceOrientation)interfaceOrientation {// 获取当前屏幕横竖屏状态 if (@available(iOS 13.0, *)) { return [UIApplication sharedApplication].windows.firstObject.windowScene.interfaceOrientation; } return [[UIApplication sharedApplication] statusBarOrientation]; }

1.2 iOS16.0调完转屏方法后,需要重新更新view的frame

问题:从电子签名界面回来之后,页脚的frame不正确

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {         UIButton *nextBtn = [ControlManager getButtonWithFrame:CGRectMake(KWratio(30), KWratio(25), kWidth - KWratio(60), KWratio(45)) fontSize:displayFontSize(15.0f) title:@"提交" titleColor:[UIColor whiteColor] image:[UIImage new] backgroundColor:BASE_RED_COLOR cornerRadius:KWratio(5)]; return xxx; }

原因:iOS16.0调用完转屏方法以后,如果不是使用自动布局,view需要重新更新frame。

解决方法:自定义页脚和页眉(UITableViewHeaderFooterView代替 titleForHeaderInSection)

1.3 自定义页脚

UITableViewHeaderFooterView代替 titleForHeaderInSection

https://blog.csdn.net/z929118967/article/details/105218766

  1. 注册FooterView

[_tableView registerClass:[CRMNextBtnHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"CRMNextBtnHeaderFooterView"];

  1. 返回FooterView

``` - (UIView )tableView:(UITableView )tableView viewForFooterInSection:(NSInteger)section {     CRMNextBtnHeaderFooterView *footerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"CRMNextBtnHeaderFooterView"];

//    footerView.models = self.viewModel.passwordRuleDescModel;

return footerView; } ```

  1. 实现FooterView

```

@interface CRMNextBtnHeaderFooterView : UITableViewHeaderFooterView

@property (nonatomic , weak) UIButton *nextBtn;

@property (nonatomic , weak) UIButton *cancelBtn;

@end ```

II 解决UITableViewCell兼容问题(iOS14适配)

https://kunnan.blog.csdn.net/article/details/108671275

2.1 问题分析

iOS14 UITableViewCell的子试图不能点击或者滑动等手势响应问题,发现有问题的cell基本都是直接添加到Cell的,通过Xcode自带的DebugViewHierarchy视图分析发现问题的原因是:被系统自带的UITableViewCellContentView遮挡在底部了

2.2 解决方案

需要改规范的做法

cell.contentView.addSubView(tempView1)

全局修改适配

``` // //  UITableViewCell+CRMaddSubView.m //  Housekeeper // //  Created by mac on 2020/9/18. //  Copyright © 2020 QCT. All rights reserved. //

import "UITableViewCell+CRMaddSubView.h"

@implementation UITableViewCell (CRMaddSubView) + (void)load {     // Swizzle addSubView     [UITableViewCell sensorsdata_swizzleMethod:@selector(addSubview:) withMethod:@selector(kunnan_addSubview:)];      }

- (void)kunnan_addSubview:(UIView *)view {

if  ([view isKindOfClass:NSClassFromString(@"UITableViewCellContentView")]) {//允许 addSubView UITableViewCellContentView                   [self kunnan_addSubview:view];//实现方法,因为已经进行了 swizzle,相当于调用原来的方法         

} else {//                  [self.contentView addSubview:view];              }

}

@end ```

III iOS10 系统关于UITableView的适配问题

因为目前基本找不到iOS10的真机了,要测试iOS10 可以下载模拟器。

  1. tableView numberOfRowsInSection:QCTReceiptsubFilterViewSection4KeyTypeTitle] 的使用执行顺序在iOS10的很特殊,不能在在方法中 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section调用,否则会造成死循环。
  2. heightForFooterInSection 在iOS10 即使高度返回0 也会显示视图

3.1 代理方法的执行顺序

tableView:numberOfRowsInSection 不能在方法中 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{调用,否则会造成死循环。

3.2 尾部视图的展示

在iOS10 中不显示viewForFooterInSection的正确做法是,将tableView:viewForFooterInSection: 和tableView:heightForFooterInSection:方法都注释掉

```

//- (CGFloat)tableView:(UITableView )tableView heightForFooterInSection:(NSInteger)section{ //     //    return 0; //     //    return kAdjustRatio(92+10); //} // //- (UIView )tableView:(UITableView )tableView viewForFooterInSection:(NSInteger)section{ //     footerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@""]; //     //    footerView.type =  self.type; //    footerView.models = self.viewModel.datas[section]; //    return footerView; //} ```