1. 程式人生 > >適配 iOS 8 時遇到的問題兩則:遠程推送和 Unwind Segue

適配 iOS 8 時遇到的問題兩則:遠程推送和 Unwind Segue

沒有 code cat ios 6 相同 padding nic else bre

原文:http://imtx.me/archives/1910.html


昨天我在微博上吐槽:iOS 8 / Xcode 6 真是史上對開發人員最糟糕的版本號了。收到非常多朋友表達同感。

之所以這麽說。倒不是針對 iOS 8 本身的特性來說的,相反,iOS 8 開放的那些擴展機制以及各種 Kit 對開發人員來說是很好。

我抱怨的是 Apple 近期對軟件質量的控制不太好。上次發一個讓手機不工作的 iOS 8.0.1 就不說了。iOS 8 / Xcode 6 本身充滿了許多的 Bug。Xcode 作為 IDE,提交 App 的時候還常常失敗。比方前幾天我提交 Manico 1.4.1 版本號,Xcode 6 還直接失敗,最後還用 Xcode 5 完畢了提交。

這讓作為開發人員的我們很窩火。

除此之外。Apple 在 iOS 上的演進越來越激烈。為了推進新的系統特性,Apple 直接 break 了軟件在升級後的向下兼容兼容特性。實在是讓我驚訝。今天就談兩則近期遇到的吧。

實際上我要記錄的這些在 Apple 的 WWDC 上應該都有提到,無奈視頻沒有所有看完。僅僅有在碰到問題的時候才去解決。

遠程推送機制的變化

假設你還在代碼裏用 registerForRemoteNotificationTypes 這種方法來註冊推送功能。你的 App 又用 iOS 8 的 SDK 編譯了。那麽你的 App 在 iOS 8 下將無法註冊功能推送(在 iOS 7 下是能夠的)。

Apple 直接將這個 API 在 iOS 8 下設置成了「無法工作」。而不是簡單的標記了 deprecated。

那麽在 iOS 8 下用哪個 API 去註冊遠程推送功能?用新的 API:registerForRemoteNotifications。

可是,這個 API,只會註冊一個靜默功能的遠程推送,雖然 App 之後會收到推送並進行處理,它不會在用戶界面上有不論什麽提示。

那麽怎樣在 iOS 8 下完畢和 iOS 7 下一樣的遠程推送註冊支持?以下的代碼能夠讓推送的支持在 iOS 7 和 iOS 8 下都正常工作,if 裏面的是 iOS 8 的,而 else 那裏是 iOS 7。

UIApplication
*application = [UIApplication sharedApplication]; if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert) categories:nil]; [application registerUserNotificationSettings:settings]; [application registerForRemoteNotifications]; } else { [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)]; }

能夠看到,iOS 8 把原先一步到位的 RemoteNotification 的註冊分成兩部分,一部分是註冊新引入的那個「UIUserNotificationSettings」,還有一部分才是 RemoteNotifications。

Apple 為什麽要這樣設計?

簡單的說,Apple 在 iOS 8 將 RemoteNotification 和 LocalNotification 統一了起來。

兩種 Notifications 將統一由 UIUserNotificationSettings 來管理用戶界面相關的東西:標記、聲音和提醒。除了統一用戶界面的通知外,UIUserNotificationSettings 還引入了 UIUserNotificationCategory,能夠讓用戶方便的直接在 Notification 上進行一些快捷的操作(Action)。這部分我還沒玩過,所以又不多講了。

總之。Apple 為了推進新的技術,不惜直接把老的 API 弄成不工作,實在是讓人驚嘆…

Unwind Segue 的變化

Unwind Segue 是 Storyboard 裏面一項我非常喜歡並且有用的技術。通過 Unwind,能夠非常方便的在同一層級(通過 Push 進行)和不同層級(通過 Modal 進行)的 ViewController 之間進行回退,僅僅要前面的 ViewController 有一個實現了特定的 Unwind。那麽在當前的 ViewController 運行這個 Unwind,就會回跳到前面的某個 ViewController,無論中間隔了幾個,都能準確的跳回去。

喜歡這個技術主要是由於 Unwind 比 Delegate 更靈活。ViewController 中間能夠隔好幾個,不須要用 delegate 關聯起來,僅僅要實現特定的 Unwind 方法就能夠了。

然而,在 iOS 8 其中。非常遺憾的。Unwind 不再像曾經一樣好好工作了:假設你的 ViewController 是基於NavigationController。那麽如今它僅僅支持同一層級的 ViewController 之間的相互跳轉(即通過 Push 方式產生的),而不支持不同層級的 ViewController 之間的相互跳轉了(即通過 Modal 形式產生)。

Apple 沒有什麽 Depcated 的 Warning,直接就讓 Modal 形式的 ViewController 下運行 Unwind 不工作了,沒有不論什麽錯誤和提示…

關於這個,StackOverflow 上有一個討論:Unwind Segue not working in iOS 8

眼下為止,沒有一個好辦法(包含那個被接受的 Answer 實際上了不行),眼下為止我發現最好的辦法就是重寫相關代碼,然後用 delegate 去實現。假設你有更好的辦法,請記得告訴我。

後記

因為我差點兒相同是 iOS 7 時代才開始正式做 iOS 開發的,我不知道曾經 Apple 從 iOS 5 -> iOS 6,從 iOS 6 -> iOS 7 有沒有過類似的直接把某個 API 弄為不工作,而不是循序漸進的 deprecated 的過程。

總之這次讓我真切的體驗會到新舊版本號切換時作為開發人員的陣痛,且不說破壞 API 的向下兼容究竟合不合適,光是 iOS 8 / Xcode 6 裏各種令人無奈的 Bug 就讓人足夠頭疼了。還是希望 Apple 能在 Xcode 6.1 裏把問題變得少一些。

接下去,我要去適配 Manico 的 Yosemite 風格了…


適配 iOS 8 時遇到的問題兩則:遠程推送和 Unwind Segue