標籤:ios8 xcode
原文: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