第九篇:swift4.0、iPhone X、iOS 11的適配工作

weixin_34247155發表於2017-10-11

iPhone X的適配工作

1、閃屏(啟動頁)適配

目前Xcode9.0已結可以更新了,更新了Xcode的朋友在iPhone X的模擬器下執行APP,發現螢幕未充滿 ps:啟動頁使用LaunchImage的情況 ,這種情況大家也基本都知道,這是缺少啟動圖的原因。

解決辦法:

LaunchImage 中新增一個和 iPhone X 相關的啟動圖片 
圖片尺寸:1125 * 2436 
Contents.json 中程式碼如下
{
    "extent" : "full-screen",
    "idiom" : "iphone",
    "subtype" : "2436h",
    "filename" : "1125_2436.png",
    "minimum-system-version" : "11.0",
    "orientation" : "portrait",
    "scale" : "3x"
}

2、安全區域問題Safe Area

iPhone X 取消了 Home鍵,實現了高屏佔比,所以預設 View 的區域是全螢幕
螢幕四周有圓角、頂部有“劉海”、底部有手勢區域
所以頂部導航欄就變為了44+44=88(iPhone X之前的都為20+44=64)

解決方法:

//導航欄高度
let NavigationBarHeight = statusBarHeight + CGFloat(44.0)
//時間欄的高度
let statusBarHeight = iPhoneX ? CGFloat(34) : CGFloat(20)

ps:關於iPhone X的底部適配,目前還沒找到好的適配方式,因為使用的第三方的自動佈局庫,現在還沒有更好的方式,所以暫時擱置了,持續更新中。。。

iOS 11的適配工作

1、UITableview UICollectionView MJRefresh下拉重新整理錯亂

如果有一些文字位於UI滾動檢視的內部,幷包含在導航控制器中,現在一般navigationContollers會傳入一個contentInset給其最頂層的viewController的scrollView,在iOS11中進行了一個很大的改變,不再通過scrollView的contentInset屬性了,而是新增了一個屬性:adjustedContentInset。

contentInsetAdjustmentBehavior屬性有以下幾個列舉值

typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {  
    UIScrollViewContentInsetAdjustmentAutomatic, 
    UIScrollViewContentInsetAdjustmentScrollableAxes,
    UIScrollViewContentInsetAdjustmentNever,
    UIScrollViewContentInsetAdjustmentAlways,
}

@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior;
@property(nonatomic, readonly) UIEdgeInsets adjustedContentInset;

//adjustedContentInset值被改變的delegate
- (void)adjustedContentInsetDidChange; 
- (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView;

1、 automatic 和scrollableAxes一樣,scrollView會自動計算和適應頂部和底部的內邊距並且在scrollView 不可滾動時,也會設定內邊距.
2、 scrollableAxes 自動計算內邊距.
3、 never不計算內邊距
4、 always 根據safeAreaInsets 計算內邊距
在我們專案中寫tableview的時候可以加下面的程式碼來解決此問題

解決辦法:如果還想保持和之前版本一樣的佈局效果,則設定:

if (@available(iOS 11.0, *)) {
    _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    _scrollview.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}

2、定位相關

問題描述:無法定位,而且程式在安裝後第一次訪問定位許可權時,無定位許可權提示對話方塊彈出。
原因:iOS11 定位相關的許可權做了更改,在iOS11上使用了新的定位許可權key。
解決方案:
如果原來申請的許可權是始終允許NSLocationAlwaysUsageDescription,那麼需要在保留原來的key的基礎上增加NSLocationWhenInUseUsageDescription和NSLocationAlwaysAndWhenInUsageDescription。

3、系統相簿相關

問題描述:iOS11上讀寫相簿的照片時發生崩潰。
原因:由於相簿相關許可權的key發生了變化。使用者在沒有許可權的情況下,訪問相簿導致崩潰。
解決方案:
iOS11之前相簿對應的key是NSPhotoLibraryUsageDescription,iOS11對應的Key是NSPhotoLibraryAddUsageDescription。同定位的Key一樣,由於key沒有相容性,所以需要保留原key以相容iOS10及之前版本。

4、第三方庫WKWebViewJavascriptBridge

問題描述:在WKWebView的回撥函式中崩潰:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
原因:WKWebViewJavascriptBridge內部邏輯問題
解決方案:WKWebViewJavascriptBridge最新的6.0.2上仍然沒有解決這個問題,可以參考github issue#272
只能手動修改原始檔,將WKWebViewJavascriptBridge.m 的L153的if改為 else if

更改前後的圖片:


3488832-c1762fa5c64c9e4f.png
20170913135248515.png

5、滑動刪除會蹦?(轉,目前還沒試驗,mark下)

在iOS8之後,蘋果官方增加了UITableVIew的右滑操作介面,即新增了一個代理方法(tableView: editActionsForRowAtIndexPath:)和一個類(UITableViewRowAction),代理方法返回的是一個陣列,我們可以在這個代理方法中定義所需要的操作按鈕(刪除、置頂等),這些按鈕的類就是UITableViewRowAction。這個類只能定義按鈕的顯示文字、背景色、和按鈕事件。並且返回陣列的第一個元素在UITableViewCell的最右側顯示,最後一個元素在最左側顯示。從iOS 11開始有了一些改變,首先是可以給這些按鈕新增圖片了,然後是如果實現了以下兩個iOS 11新增的代理方法,將會取代(tableView: editActionsForRowAtIndexPath:)代理方法:

// Swipe actions
// These methods supersede -editActionsForRowAtIndexPath: if implemented
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath

這兩個代理方法返回的是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;
}

建立UIContextualAction物件時,UIContextualActionStyle有兩種型別,如果是置頂、已讀等按鈕就使用UIContextualActionStyleNormal型別,delete操作按鈕可使用UIContextualActionStyleDestructive型別,當使用該型別時,如果是右滑操作,一直向右滑動某個cell,會直接執行刪除操作,不用再點選刪除按鈕,這也是一個好玩的更新。

滑動操作這裡還有一個需要注意的是,當cell高度較小時,會只顯示image,不顯示title,當cell高度夠大時,會同時顯示image和title。我寫demo測試的時候,因為每個cell的高度都較小,所以只顯示image,然後我增加cell的高度後,就可以同時顯示image和title了。

swift4.0的適配工作

1、指定swift4.0的版本

3488832-a8169846b34728cb.png
修改swift4.png

2、pods的第三方庫的適配

目前pods的framework只能指定一個版本的swift。issue在這裡:Pods automatically compiling with Swift 4.0 in Xcode 9 beta 1 。pod預設會使用一個swift版本編譯全部,然而並不是你所匯入的第三方庫都已經支援swift4,這就導致了一個問題就是,要麼你的第三方庫都升級為swift4.0,要麼有一個還不支援swift4就要統一使用swift3.2的版本。這是一個選擇題,由於目前swift4.0剛出沒多久,而且所有的第三方庫都支援4.0也不太現實,所以這方面的適配工作就擱置了。

3、swift4.0語法適配

  • Swift4.0中對於擴充套件的屬性(包括例項屬性、static屬性、class屬性),都只能使用get方法,不可使用set方法

  • Swift4.0中不再允許複寫擴充套件中的方法(包括例項方法、static方法、class方法)

  • swift3使用#selector指定的方法,只有當方法許可權為private時需要加@objc修飾符,現在全都要加@objc修飾符(這是最坑的!!!)

  • 字型方面的一些重新命名:
    (NSFontAttributeName重新命名為NSAttributedStringKey.font、NSForegroundColorAttributeName重新命名為NSAttributedStringKey.foregroundColor、NSStrikethroughStyleAttributeName重新命名為NSAttributedStringKey.strikethroughStyle、size(withAttributes:)方法重新命名為size(withAttributes:))

ps:針對#selector指定的方法都要新增@objc修飾符問題,這才是最坑的!!!至於原因,這裡有一篇文章說明 如何解決#selector的引數是指不暴露給Objective-C的例項方法,大家可以看看,我就不在這類羅列了,因為pods問題和#selector問題,使我暫時沒有去適配swift4.0,還保持swift3.2版本開發,在觀望觀望吧。。。

相關文章