iOS11及Xcode9適配問題彙總


UIScrollView and UITableView的新特性

ScrollView

若是有一些文本位於UI滾動視圖的內部,幷包含在導航控制器中,如今通常navigationContollers會傳入一個contentInset給其最頂層的viewController的scrollView,在iOS11中進行了一個很大的改變,再也不經過scrollView的contentInset屬性了,而是新增了一個屬性:adjustedContentInset,經過下面兩種圖的對比,可以表示adjustContentInset表示的區域:ios



新增的contentInsetAdjustmentBehavior屬性用來配置adjustedContentInset的行爲,該結構體有如下幾種類型:數組

typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
緩存

UIScrollViewContentInsetAdjustmentAutomatic,安全

UIScrollViewContentInsetAdjustmentScrollableAxes,app

UIScrollViewContentInsetAdjustmentNever,ide

UIScrollViewContentInsetAdjustmentAlways,測試

}動畫

@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior;ui

@property(nonatomic, readonly) UIEdgeInsets adjustedContentInset;atom

//adjustedContentInset值被改變的delegate

- (void)adjustedContentInsetDidChange;

- (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView;

UIScrollViewContentInsetAdjustmentBehavior 是一個枚舉類型,值有如下幾種:

一、automatic 和scrollableAxes同樣,scrollView會自動計算和適應頂部和底部的內邊距而且在scrollView 不可滾動時,也會設置內邊距.

二、scrollableAxes 自動計算內邊距.

三、never不計算內邊距

四、always 根據safeAreaInsets 計算內邊距

TableView

1.UITableview UICollectionView MJRefresh下拉刷新錯亂或是莫名有20空隙的問題

if (@available(iOS 11.0, *)) {

_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;

_tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);//iPhoneX這裏是88

_tableView.scrollIndicatorInsets = _tableView.contentInset;

}

若是改完後運行無效果 能夠嘗試Clean一下工程再運行, 不少小夥伴都遇到這樣的問題了, 你不妨也試以試.

2.在iOS 11中默認啓用Self-Sizing 未使用AutoLayout的TableView中的高度會出現問題.

Self-Sizing在iOS11下是默認開啓的,Headers, footers, and cells都默認開啓Self-Sizing,全部estimated高度默認值從iOS11以前的0改變爲UITableViewAutomaticDimension.

若是目前項目中沒有使用estimateRowHeight屬性,在iOS11的環境下就要注意了,由於開啓Self-Sizing以後,tableView是使用estimateRowHeight屬性的,這樣就會形成contentSize和contentOffset值的變化,若是是有動畫是觀察這兩個屬性的變化進行的,就會形成動畫的異常,由於在估算行高機制下,contentSize的值是一點點地變化更新的,全部cell顯示完後纔是最終的contentSize值。由於不會緩存正確的行高,tableView reloadData的時候,會從新計算contentSize,就有可能會引發contentOffset的變化。iOS11下不想使用Self-Sizing的話,能夠經過如下方式關閉:

self.tableView.estimatedRowHeight = 0;

self.tableView.estimatedSectionHeaderHeight = 0;

self.tableView.estimatedSectionFooterHeight = 0;

3.TableView的separatorInset擴展

iOS 7 引入separatorInset屬性,用以設置 cell 的分割線邊距,在 iOS 11 中對其進行了擴展。能夠經過新增的UITableViewSeparatorInsetReference枚舉類型的separatorInsetReference屬性來設置separatorInset屬性的參照值.

經過下面的參考圖能夠看出他們的區別:


4. TableView和SafeArea(安全區)

有如下幾點須要注意:

separatorInset被自動地關聯到 safe area insets,所以,默認狀況下,表視圖的整個內容避免了其根視圖控制器的安全區域的插入。

UITableviewCell和UITableViewHeaderFooterView的contentview在安全區域內;所以你應該始終在contentview中使用add-subviews操做。

全部的 headers 和 footers 都應該使用UITableViewHeaderFooterView,包括 table headers 和 footers、section headers 和 footers。

5. TableView的滑動操做

在iOS8以後,蘋果官方增長了UITableVIew的右滑操做接口,即新增了一個代理方法tableView: editActionsForRowAtIndexPath:和一個類UITableViewRowAction,代理方法返回的是一個數組,咱們能夠在這個代理方法中定義所須要的操做按鈕(刪除、置頂等),這些按鈕的類就是UITableViewRowAction。這個類只能定義按鈕的顯示文字、背景色、和按鈕事件。而且返回數組的第一個元素在UITableViewCell的最右側顯示,最後一個元素在最左側顯示。從iOS 11開始有了一些改變,首先是能夠給這些按鈕添加圖片了,而後是若是實現瞭如下兩個iOS 11新增的代理方法,將會取代tableView: editActionsForRowAtIndexPath:代理方法:


這兩個代理方法返回的是UISwipeActionsConfiguration類型的對象,建立該對象及賦值可看下面的代碼片斷:

- ( UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {

//刪除

UIContextualAction *deleteRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"delete" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {

[self.titleArr removeObjectAtIndex:indexPath.row];

completionHandler (YES);

}];

deleteRowAction.image = [UIImage imageNamed:@"icon_del"];

deleteRowAction.backgroundColor = [UIColor blueColor];

UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction]];

return config;

}

typedef NS_ENUM(NSInteger, UIContextualActionStyle) {

UIContextualActionStyleNormal,

UIContextualActionStyleDestructive

} NS_SWIFT_NAME(UIContextualAction.Style)

建立UIContextualAction對象時,UIContextualActionStyle有兩種類型,若是是置頂、已讀等按鈕就使用UIContextualActionStyleNormal類型,delete操做按鈕可以使用UIContextualActionStyleDestructive類型,當使用該類型時,若是是右滑操做,一直向右滑動某個cell,會直接執行刪除操做,不用再點擊刪除按鈕,這也是一個好玩的更新.

typedef NS_ENUM(NSInteger, UIContextualActionStyle) {

UIContextualActionStyleNormal,

UIContextualActionStyleDestructive

} NS_SWIFT_NAME(UIContextualAction.Style)

滑動操做這裏還有一個須要注意的是,當cell高度較小時,會只顯示image,不顯示title,當cell高度夠大時,會同時顯示image和title。我寫demo測試的時候,由於每一個cell的高度都較小,因此只顯示image,而後我增長cell的高度後,就能夠同時顯示image和title了。見下圖對比:


iOS11中 UIKit’s Bars 上的變化

WWDC經過iOS新增的文件管理App:Files開始介紹,在Files這個APP中可以看到iOS11中UIKit’s Bars的一些新特性:在瀏覽功能上的大標題視圖(向上滑動後標題會回到原來的UI效果)、橫屏狀態下tab上的文字和icon會變爲左右排列:



在iPhone上,tab上的圖標較小,tab bar較小,這樣垂直空間可多放置內容。若是有人看不清楚tab bar上的圖標或文字,能夠經過長按tab bar上的任意item,會將該item顯示在HUD上,這樣能夠清楚的看清icon和text。對tool bar 和 navigation bar同理,長按item也會放大顯示.

UIBarItem

UIBarItem是UI tab bar item和UI bar button item的父類,要想實現上面介紹的效果,只須要爲UIBarItem 設置landscapeImagePhone屬性,在storyboard中也支持這個設置,對於HUD的image須要設置另外一個iOS11新增的屬性:largeContentSizeImage,關於這部分更詳細的討論,能夠參考WWDC2017 Session 215:What's New in Accessibility

控制大標題的顯示

在UINavigationbar中新增了一個BOOL屬性prefersLargeTitles,將該屬性設置爲ture,navigationbar就會在整個APP中顯示大標題,若是想要在控制不一樣頁面大標題的顯示,能夠經過設置當前頁面的navigationItem的largeTitleDisplayMode屬性.

navigationItem.largeTitleDisplayMode

typedef NS_ENUM(NSInteger, UINavigationItemLargeTitleDisplayMode) {

/// 自動模式依賴上一個 item 的特性

UINavigationItemLargeTitleDisplayModeAutomatic,

/// 針對當前 item 老是啓用大標題特性

UINavigationItemLargeTitleDisplayModeAlways,

/// Never

UINavigationItemLargeTitleDisplayModeNever,

}

在 Navigation 集成 UISearchController

把你的UISearchController賦值給navigationItem,就能夠實現將UISearchController集成到 Navigation.

navigationItem.searchController  //iOS 11 新增屬性

navigationItem.hidesSearchBarWhenScrolling //決定滑動的時候是否隱藏搜索框;iOS 11 新增屬性

UINavigationController和滾動交互

滾動的時候,如下交互操做都是由UINavigationController負責調動的:

UIsearchController搜索框效果更新

大標題效果的控制

Rubber banding效果 //當你開始往下拉,大標題會變大來回應那個滾輪

因此,若是你使用navigation bar,組裝一些總體push和pop體驗,你不會獲得searchController的集成、大標題的控制更新和Rubber banding效果,由於這些都是由UINavigationController控制的。

Margins 和 Insets

基於約束的Auto Layout, 使咱們搭建可以動態響應內部和外部變化的用戶界面. Auto Layout爲每個view都定義了margin.margin指的是控件顯示內容部分的邊緣和控件邊緣的距離.

能夠用layoutMargins或者layoutMarginsGuide屬性得到view的margin,margin是視圖內部的一部分.layoutMargins容許獲取或者設置UIEdgeInsets結構的margin.layoutMarginsGuide則獲取到只讀的UILayoutGuide對象.

在iOS11新增了一個屬性:directional layout margins,該屬性是NSDirectionalEdgeInsets結構體類型的屬性:

typedef struct NSDirectionalEdgeInsets {

CGFloat top, leading, bottom, trailing;

} NSDirectionalEdgeInsets API_AVAILABLE(ios(11.0),tvos(11.0),watchos(4.0));

layoutMargins是UIEdgeInsets結構體類型的屬性:

typedef struct UIEdgeInsets {

CGFloat top, left, bottom, right;

} UIEdgeInsets;

從上面兩種結構體的對比能夠看出,NSDirectionalEdgeInsets屬性用leading和trailing取代了以前的left和right.

directional layout margins屬性的說明以下:

directionalLayoutMargins.leading is used on the left when the user interface direction is LTR and on the right for RTL.

Vice versa for directionalLayoutMargins.trailing.

例子: 當你設置了trailing = 30;當在一個right to left 語言下trailing的值會被設置在view的左邊, 能夠經過layoutMargin的left屬性讀出該值. 以下圖所示:


還有其餘一些更新. 自從引入layout margins, 當將一個view添加到viewController時,viewController會修改view的layoutMargins爲UIKit定義的一個值, 這些調整對外是封閉的. 從iOS11開始, 這些再也不是一個固定的值, 它們實際是最小值, 你能夠改變view的layoutMargins爲任意一個更大的值. 並且,viewController新增了一個屬性:viewRespectsSystemMinimumLayoutMargins, 若是你設置該屬性爲false, 你就能夠改變你的layoutMargins爲任意你想設置的值, 包括0, 以下圖所示:


個人大神LEE

本文轉載LEE

相關文章
相關標籤/搜索