為App適配iOS11
TableView
當tableview的style為grouped的時候,會出現每個section之間有間距。
官方解析:Link on iOS 11, all estimated heights default to UITableViewAutomaticDimension Headers, footers, and cells use self-sizing by default.
- 解決方案:
如果開發者不想用這個新特性,可以在代理方法裏面設置具體的高度,然後設置
tableView.estimatedRowHeight = 0
tableView.estimatedSectionHeaderHeight = 0
tableView.estimatedSectionFooterHeight = 0
TitleView
因為iOS11 的navbar的大標題和搜索欄的新特性,navbar的子視圖發生了變化。 如果沒有給出明確的長寬,就會出現Zero-size的出現,就是說titleview不見了,或者各種奇怪的事情出現。
- 解決方案:
- 給出指定的長寬,和子view設置好對應的約束。
- 或者重寫intrinsicContentSize方法,設置成UILayoutFittingExpandedSize,讓它自己自動擴展。
@available(iOS 6.0, *)
public let UIViewNoIntrinsicMetric : CGFloat
// Size To Fit
@available(iOS 6.0, *)
public let UILayoutFittingCompressedSize: CGSize
@available(iOS 6.0, *)
public let UILayoutFittingExpandedSize: CGSize
如果設置成擴展的話titleView和兩邊的item粘在一起了,所以需要做一下子視圖的布局。
題外話: iOS6有一個API,systemLayoutSizeFitting,可以根據view的約束計算出對應的大小,具體可以看API文檔。
Safe Area
這個主要影響用到mj的列表頁面,和隱藏navbar的列表頁面。
Safe Area是系統自己算的,系統會根據state bar的高度,navbar、tabbar是否透明(isTranslucent)。
每個view都有一個叫safeAreaInsets的屬性(get only)。 如果開發者需要更改view的safe area 可以在controller設置additionalSafeAreaInsets去屬性去弄。
例如:
帶有navbar,和tabbar的頁面。
controller.view.safeAreaInsets 為 UIEdgeInsets(top: 64.0, left: 0.0, bottom: 49.0, right: 0.0)
如果想改為(20,0,49,0)只需要做如下操作。
controller.view.additionalSafeAreaInsets = UIEdgeInsets(top: -44.0, left: 0.0, bottom: -49.0, right: 0.0)
其實無論設置成(-20000,0,0,0)也是最終得到的(20,0,49,0),還有就是無論設置bottom為-49還是其他的值,都無法抵消tabbar的高度,也就是說系統不允許我們去縮減bottom的值,可能是因為iPhoneX的底部虛擬home鍵。
view.safeAreaInsets是影響其子ScrollView的adjustedContentInset。 ScrollView會根據contentInsetAdjustmentBehavior屬性去設置 adjustedContentInset。
public enum UIScrollViewContentInsetAdjustmentBehavior : Int {
case automatic // Similar to .scrollableAxes, but for backward compatibility will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller, regardless of whether the scroll view is scrollable
case scrollableAxes // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)
case never // contentInset is not adjusted
case always // contentInset is always adjusted by the scroll view‘s safeAreaInsets
}
- UIScrollViewContentInsetAdjustmentAutomatic:如果scrollview在一個automaticallyAdjustsScrollViewContentInset = YES的controller上,並且這個Controller包含在一個navigation controller中,這種情況下會設置在top & bottom上 adjustedContentInset = safeAreaInset + contentInset不管是否滾動。其他情況下與UIScrollViewContentInsetAdjustmentScrollableAxes相同
- UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滾動方向上adjustedContentInset = safeAreaInset + contentInset,在不可滾動方向上adjustedContentInset = contentInset;依賴於scrollEnabled和alwaysBounceHorizontal / vertical = YES,scrollEnabled默認為yes,所以大多數情況下,計算方式還是adjustedContentInset = safeAreaInset + contentInset
- UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset
- UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset
- 使用MJ的列表頁的適配方案
if #available(iOS 11, *) {
t.contentInset.top += kTopBarHeight
t.contentInset.bottom += kHomeBarHeight // 如果列表底部沒有任何toolbar的需要添加,為了適配iPhone X
t.contentInsetAdjustmentBehavior = .never
}
底層API命名改變
例如我使用一些第三方庫的時候,它們有用到一些API如check_compile_time() 在iOS11裏面的命名改變為__Check_Compile_Time()。
-解決方案:
找到對應的頭文件,搜索舊的API一般都有說明的。
/*
* For time immemorial, Mac OS X has defined version of most of these macros without the __ prefix, which
* could collide with similarly named functions or macros in user code, including new functionality in
* Boost and the C++ standard library.
*
* macOS High Sierra and iOS 11 will now require that clients move to the new macros as defined above.
*
* If you would like to enable the macros for use within your own project, you can define the
* __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES macro via an Xcode Build Configuration.
* See "Add a build configuration (xcconfig) file" in Xcode Help.
*
* To aid users of these macros in converting their sources, the following tops script will convert usages
* of the old macros into the new equivalents. To do so, in Terminal go into the directory containing the
* sources to be converted and run this command.
*
find . -name ‘*.[c|cc|cp|cpp|m|mm|h]‘ -print0 | xargs -0 tops -verbose \
replace "check(<b args>)" with "__Check(<args>)" replace "check_noerr(<b args>)" with "__Check_noErr(<args>)" replace "check_noerr_string(<b args>)" with "__Check_noErr_String(<args>)" replace "check_string(<b args>)" with "__Check_String(<args>)" replace "require(<b args>)" with "__Require(<args>)" replace "require_action(<b args>)" with "__Require_Action(<args>)" replace "require_action_string(<b args>)" with "__Require_Action_String(<args>)" replace "require_noerr(<b args>)" with "__Require_noErr(<args>)" replace "require_noerr_action(<b args>)" with "__Require_noErr_Action(<args>)" replace "require_noerr_action_string(<b args>)" with "__Require_noErr_Action_String(<args>)" replace "require_noerr_string(<b args>)" with "__Require_noErr_String(<args>)" replace "require_string(<b args>)" with "__Require_String(<args>)" replace "verify(<b args>)" with "__Verify(<args>)" replace "verify_action(<b args>)" with "__Verify_Action(<args>)" replace "verify_noerr(<b args>)" with "__Verify_noErr(<args>)" replace "verify_noerr_action(<b args>)" with "__Verify_noErr_Action(<args>)" replace "verify_noerr_string(<b args>)" with "__Verify_noErr_String(<args>)" replace "verify_string(<b args>)" with "__Verify_String(<args>)" replace "ncheck(<b args>)" with "__nCheck(<args>)" replace "ncheck_string(<b args>)" with "__nCheck_String(<args>)" replace "nrequire(<b args>)" with "__nRequire(<args>)" replace "nrequire_action(<b args>)" with "__nRequire_Action(<args>)" replace "nrequire_action_quiet(<b args>)" with "__nRequire_Action_Quiet(<args>)" replace "nrequire_action_string(<b args>)" with "__nRequire_Action_String(<args>)" replace "nrequire_quiet(<b args>)" with "__nRequire_Quiet(<args>)" replace "nrequire_string(<b args>)" with "__nRequire_String(<args>)" replace "nverify(<b args>)" with "__nVerify(<args>)" replace "nverify_string(<b args>)" with "__nVerify_String(<args>)" replace "require_action_quiet(<b args>)" with "__Require_Action_Quiet(<args>)" replace "require_noerr_action_quiet(<b args>)" with "__Require_noErr_Action_Quiet(<args>)" replace "require_noerr_quiet(<b args>)" with "__Require_noErr_Quiet(<args>)" replace "require_quiet(<b args>)" with "__Require_Quiet(<args>)" replace "check_compile_time(<b args>)" with "__Check_Compile_Time(<args>)" replace "debug_string(<b args>)" with "__Debug_String(<args>)"
*
*/
參考文章
官方適配iOS11原文
譯文
safe area
為App適配iOS11