前幾天剛剛用Xcode8打包發(fā)布了1.4.0版本搪柑,然后馬上iOS11就發(fā)布了,當(dāng)時(shí)還想著要不要撤回來(lái)索烹,不然沒(méi)有適配在iOS11上豈不是亂了工碾。后來(lái)發(fā)現(xiàn)是多慮了,因?yàn)槭怯肵code8打的包百姓,所以不會(huì)有很大問(wèn)題渊额。伴隨著iOS11發(fā)布,Xcode9也更新了垒拢,用Xcode9打包的話需要適配好旬迹,不然真的會(huì)亂的。
下面就介紹下適配過(guò)程中一些問(wèn)題和解決辦法求类。
適配iOS 11
1 有些頁(yè)面UITableView顯示不全
原因:在這些頁(yè)面我都使用到了UITableView的contentSize奔垦,比如下面這個(gè)
- (void)reloadScrollView
{
CGFloat top = 0;
[self.pictureView setZy_Top:top];
top = top + self.pictureView.zy_height;
[self.viewChange setZy_Top:top];
top = top + self.viewChange.zy_height;
[self.tableViewFitment setZy_Top:top];
[self.tableViewFitment setZy_Height:self.tableViewFitment.contentSize.height];
top = top + self.tableViewFitment.contentSize.height + 20;
[self.viewBottom setZy_Top:top];
top = top + self.viewBottom.zy_height;
self.mainScrollView.contentSize = CGSizeMake(kWidthScreen, top);
}
參考文章你可能需要為你的 APP 適配 iOS 11
在iOS11中默認(rèn)開(kāi)啟了Self-Sizing,這個(gè)應(yīng)該是UITableView最大的改變尸疆。在iOS8引入Self-Sizing之后椿猎,我們可以通過(guò)實(shí)現(xiàn)estimatedRowHeight相關(guān)的屬性來(lái)展示動(dòng)態(tài)的內(nèi)容,實(shí)現(xiàn)了estimatedRowHeight屬性后仓技,得到的初始contentSize是個(gè)估算值鸵贬,是通過(guò)estimatedRowHeight 乘以 cell的個(gè)數(shù)得到的,并不是最終的contentSize脖捻,tableView就不會(huì)一次性計(jì)算所有的cell的高度了阔逼,只會(huì)計(jì)算當(dāng)前屏幕能夠顯示的cell個(gè)數(shù)再加上幾個(gè),滑動(dòng)的時(shí)候tableView不停地得到新的cell地沮,更新自己的contentSize嗜浮,在滑到最后的時(shí)候羡亩,會(huì)得到正確的contentSize。
Self-Sizing在iOS11下是默認(rèn)開(kāi)啟的危融,Header畏铆,footers,and Cells都默認(rèn)開(kāi)啟Self-Sizing吉殃,所有estimated高度默認(rèn)值從iOS11之前的0變?yōu)閁ITableViewAutomaticDimension辞居。如果項(xiàng)目中沒(méi)有使用estimatedRowHeight屬性,在iOS11的環(huán)境下就要注意了蛋勺,因?yàn)殚_(kāi)啟Self-Sizing之后瓦灶,tableView是使用estimatedRowHeight屬性的,這樣就會(huì)造成contentSize和contentOffset值的變化抱完,如果是有動(dòng)畫(huà)觀察這兩個(gè)屬性的變化進(jìn)行的贼陶,就會(huì)造成動(dòng)畫(huà)的異常,因?yàn)樵诠浪阈懈邫C(jī)制下巧娱,contentSize的值是一點(diǎn)點(diǎn)地變化更新的碉怔,所有cell顯示完后才是最終的contentSize值。因?yàn)椴粫?huì)緩存正確的行高禁添,tableView reloadData的時(shí)候撮胧,會(huì)重新計(jì)算contentSize,就有可能引起contentOffset的變化上荡。
iOS11下不想使用Self-Sizing的話趴樱,可以通過(guò)以下方式關(guān)閉:
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
2 UINavigationBar 上面 titleView 為 UISearchBar的時(shí)候,界面顯示異常
如圖酪捡,searchBar高度會(huì)向下變高,參考文章參考文章1 參考文章2
解決辦法纳账,將UISearchBar放到一個(gè)View上逛薇,然后將此view作為titleView,參考代碼如下
let wrapView = UIView(frame: CGRect(x: 60, y: 0, width: SCREENWIDTH - 80, height: 44))
wrapView.addSubview(self.searchBar)
self.navigationItem.titleView = wrapView
但是還是顯示有點(diǎn)問(wèn)題,searchBar背景有點(diǎn)灰顏色疏虫。設(shè)置一下背景圖片就可以了永罚。
let searchBarBg = UIImage.createImage(with: UIColor.clear)
self.searchBar.backgroundImage = searchBarBg
3 消息通知界面tableView往上移動(dòng)了,
參考文章
iOS11中automaticallyAdjustsScrollViewInsets屬性失效了卧秘,增加了contentInsetAdjustmentBehavior屬性呢袱,automaticallyAdjustsScrollViewInsets是viewController的屬性,默認(rèn)為true翅敌,一般來(lái)說(shuō)如果scrollView直接添加到控制器視圖上時(shí)羞福,會(huì)自動(dòng)設(shè)置scroll的inset屬性來(lái)空出status bar, search bar, navigationBar, toolBar等的位置來(lái),在日常的開(kāi)發(fā)中為了程序的穩(wěn)定性與自由度一般我們是將這個(gè)屬性設(shè)置為false蚯涮。但是治专,這個(gè)屬性現(xiàn)在失效了卖陵,所以會(huì)導(dǎo)致上面的問(wèn)題。
解決辦法很容易张峰,如下
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0)
tableView.scrollIndicatorInsets = tableView.contentInset
}
4 UINavigationBar顯示出問(wèn)題
參考文章
相較于iOS11之前的版本泪蔫,UINavigationBar結(jié)構(gòu)上也與之前不同,如下圖所示
可以看出喘批,原來(lái)的UINavigationItemView 被替換為 UINavigationBarContentView了撩荣。一般的方法是寫(xiě)個(gè)子類(lèi)繼承UINavigationBar,然后遍歷UINavigationBar的子控件并修改frame饶深。參考文章中有說(shuō)餐曹,但是我試了下,發(fā)現(xiàn)還是有問(wèn)題粥喜,別的界面可能會(huì)受到影響凸主。所以我的辦法是直接修改背景為白色,然后將下面那根線給刪掉额湘,自己加一個(gè)線卿吐。
參考代碼如下:
fileprivate lazy var navBar: UINavigationBar = {
let navBar = UINavigationBar()
navBar.setBackgroundImage(UIImage(), for: .default)
navBar.shadowImage = UIImage()
navBar.backgroundColor = UIColor.white
return navBar
}()
5 UIScrollView頭部向下移動(dòng)了
這是也是因?yàn)閍utomaticallyAdjustsScrollViewInsets失效,增加了contentInsetAdjustmentBehavior的原因锋华,跟上面一樣嗡官。
解決辦法,是使用runtime毯焕,將UIScrollView的contentInsetAdjustmentBehavior屬性默認(rèn)置為never衍腥,代碼如下:
@implementation UIScrollView (contentInset)
+ (void)load {
[super load];
//因?yàn)槭菫榱诉m配iOS11 所以只有在系統(tǒng)是iOS11的時(shí)候用過(guò)運(yùn)行時(shí)修改這個(gè)值
if (@available(iOS 11.0, *)) {
Method originalM = class_getInstanceMethod([self class], @selector(initWithFrame:));
Method exchangeM = class_getInstanceMethod([self class], @selector(cl_initWithFrame:));
method_exchangeImplementations(originalM, exchangeM);
}
}
- (instancetype)cl_initWithFrame:(CGRect)frame {
if (@available(iOS 11.0, *)) {
self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
// Fallback on earlier versions
}
return [self cl_initWithFrame:frame];
}
@end
適配iPhone X
其實(shí)很簡(jiǎn)單,就是就是狀態(tài)欄由20改為了44纳猫,底部的tab高度由49改為了82婆咸,給你幾個(gè)宏就行。
判斷是否為iPhone X方法
+ (BOOL)isiPhoneX
{
UIApplication *app = [UIApplication sharedApplication];
UIView *statusBar = [app valueForKey:@"statusBar"];
if ([statusBar isKindOfClass:NSClassFromString(@"UIStatusBar_Modern")]) {
return YES;
} else {
return NO;
}
}
以后就不要將高度寫(xiě)死了芜辕,用下面這些就好了尚骄。
#define kNavBarHeight 44.0
#define kStatusBarHeight ([UIDevice isiPhoneX] ? 44.0:20.0)
#define kStatueAddHeight (kStatusBarHeight - 20.0)
#define kTopHeight (kStatusBarHeight + kNavBarHeight)
#define kTabBarHeight ([UIDevice isiPhoneX] ? 83.0:49.0)
#define kTabBarAddHeight (kTabBarHeight - 49.0)
屏幕下方那個(gè)home指示器可以隱藏掉的,方法如下:
if (@available(iOS 11.0, *)) {
[self setNeedsUpdateOfHomeIndicatorAutoHidden];
}
- (BOOL)prefersHomeIndicatorAutoHidden
{
return YES;
}