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; //} ```