首先介紹幾個(gè)屬性:
@property(nonatomic) BOOL viewRespectsSystemMinimumLayoutMargins
- UIViewController 屬性. 默認(rèn)為 YES. 視圖遵守系統(tǒng)最小
layoutMargins
YES: 視圖layoutMargins
和directionalLayoutMargins
的返回值不小于系統(tǒng)最小值(systemMinimumLayoutMargins
).
NO:layoutMargins
為完全可定制的.
所以要在 UIViewController 中添加如下代碼:
if (@available(iOS 11.0, *)) {
self.viewRespectsSystemMinimumLayoutMargins = NO;
}
@property (nonatomic) UIEdgeInsets layoutMargins
@property (nonatomic) NSDirectionalEdgeInsets directionalLayoutMargins
- UIView 屬性. 設(shè)置視圖邊緣.
layoutMargins
為iOS8后可用.directionalLayoutMargins
為iOS11可用, 相當(dāng)于layoutMargins
的升級(jí)版. iOS11后, 建議使用directionalLayoutMargins
.
下面是如何實(shí)現(xiàn):
- 核心代碼:
tableView.layoutMargins = UIEdgeInsetsZero;
或者
tableView.directionalLayoutMargins = NSDirectionalEdgeInsetsZero;
但是如果為每個(gè) UITabelView 都修改該屬性, 工作量會(huì)很大. 所以, 采用創(chuàng)建UITabelView 的 category 方法, 利用 runtime 在初始化的時(shí)候修改該屬性, 便可達(dá)到適配的目的.
代碼實(shí)現(xiàn):
#import "UITableView+Fix.h"
#import <objc/runtime.h>
@implementation UITableView (Fix)
+ (void)load
{
//交換實(shí)現(xiàn)
if ([[UIDevice currentDevice].systemVersion floatValue] >= 11.0) {
//代碼創(chuàng)建(調(diào)用initWithFrame:style:方法)
Method sysMethod = class_getInstanceMethod([self class], @selector(initWithFrame:style:));
Method fixMethod = class_getInstanceMethod([self class], @selector(fix_initWithFrame:style:));
method_exchangeImplementations(sysMethod, fixMethod);
//xib或sb創(chuàng)建(調(diào)用initWithCoder:方法)
Method xSysMethod = class_getInstanceMethod([self class], @selector(initWithCoder:));
Method xFixMethod = class_getInstanceMethod([self class], @selector(fix_initWithCoder:));
method_exchangeImplementations(xSysMethod, xFixMethod);
}
}
- (instancetype)fix_initWithCoder:(NSCoder *)aDecoder
{
UITableView *tableView = [self fix_initWithCoder:aDecoder];
[self fixTableView:tableView];
return tableView;
}
- (instancetype)fix_initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{
UITableView *tableView = [self fix_initWithFrame:frame style:style];
[self fixTableView:tableView];
return tableView;
}
- (void)fixTableView:(UITableView *)tableView
{
/**
如果目前項(xiàng)目中沒有使用estimateRowHeight屬性俯逾,在iOS11的環(huán)境下就要注意了,因?yàn)殚_啟Self-Sizing之后铸抑,
tableView是使用estimateRowHeight屬性的班挖,這樣就會(huì)造成contentSize和contentOffset值的變化,
如果是有動(dòng)畫是觀察這兩個(gè)屬性的變化進(jìn)行的泉孩,就會(huì)造成動(dòng)畫的異常硼端,
因?yàn)樵诠浪阈懈邫C(jī)制下,contentSize的值是一點(diǎn)點(diǎn)地變化更新的寓搬,所有cell顯示完后才是最終的contentSize值珍昨。
因?yàn)椴粫?huì)緩存正確的行高,tableView reloadData的時(shí)候,會(huì)重新計(jì)算contentSize镣典,就有可能會(huì)引起contentOffset的變化
簡言之,如果項(xiàng)目中沒有使用estimateRowHeight屬性,就添加下面的代碼,不使用Self-Sizing,
不然會(huì)因?yàn)閏ontentOffset的變化,而引起一直加載的BUG
*/
tableView.estimatedRowHeight = 0;
tableView.estimatedSectionHeaderHeight = 0;
tableView.estimatedSectionFooterHeight = 0;
//處理tableView左右間距的BUG
if (@available(iOS 11.0, *)) {
tableView.directionalLayoutMargins = NSDirectionalEdgeInsetsZero;
/**
如果為 UITableViewStyleGrouped ,在UITableView設(shè)置代理之前調(diào)用directionalLayoutMargins
頂部會(huì)出現(xiàn)40 point的 tableHeaderView, 所以在調(diào)用directionalLayoutMargins之后,
設(shè)置一個(gè)高度非常小的 tableHeaderView (如果高度為0, 還是會(huì)出現(xiàn)40 point的 tableHeaderView)
*/
if (tableView.style == UITableViewStyleGrouped) {
tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)];
}
}
}
@end