iOS10發佈後,簡書優先開發增長了iOS10的新通知。本文分享整個feature的開發過程遇到的問題。git
Xcode8發生了很大的變化,直接打開原來的工程編譯運行,這個時候是獲取不到Push token的,打印didFailToRegisterForRemoteNotificationsWithError
中的error能夠看到github
fail to register with error Error Domain=NSCocoaErrorDomain Code=3000 "no valid 'aps-environment' entitlement string found for application" UserInfo={NSLocalizedDescription=no valid 'aps-environment' entitlement string found for application}
Google瞭解到是Xcode8的變化,entitlements
由本地的entitlements文件配置,主Target的Capabilities下,Push Notification
處於關閉的狀態,必須手動打開。shell
工程增長了Notification Content
和Notification Service
兩個Extension,Signing
默認是自動模式.。json
據網上介紹Xcode8簽名管理方式比Xcode7更智能,那我就試一下吧。選完Team它就自動生成了受權文件。然而,Xcode8還幫我生成了一個新的證書,至關於增長了一個開發人員,也就是我如今的證書不在原來的受權文件中,後果就是原來手動配置的受權文件要從新生成。後端
這時候若是想使用原始的手動配置,不只要把Automatically manage signing
去掉,還要在Key Chains
裏把新生成的證書刪掉,而後在Web端生成受權文件。使用Automatically manage signing
最好把每一個Target都使用相同的方式。app
若是你在建立Target的時候開發語言選了Swift,默認是使用Swift3.0,Xcode8同時支持3.0和2.3,可能你還沒來及掌握3.0的API變化,想繼續使用2.3的API,只要在對應Target的Build Setting
中Use Legacy Swift Language Version
設爲YES就能夠繼續使用2.3。框架
工程配好以後,只有模板代碼,先跑起來寫個Hello World
再說。Command+R
以後,編譯報錯了ide
Check dependenciesNo architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=i386).
VALID_ARCHS
中沒有對應的active arch
這時須要在對應Target的Build Setting
中Valid Architectures
中增長arm64
測試
接下來,開始代碼編寫了,大部分是參考喵神的這篇文章活久見的重構 - iOS 10 UserNotifications 框架解析和Demo、還有WWDC 708 Advanced Notifications、PDF。
在service中,咱們會把後端push過來的數據中的圖片下載到本地文件夾,而後做爲attachments。
以前咱們的推送都只顯示一句alert,不過推送的json數據alert字段能夠是string,也能夠是dictionary,若是是string,至關於dictionary中的body
,在iOS8.2以後dictionary能夠增長title
、subtitle
等。爲了讓推送更豐富,咱們想把原來的body
變成title
,增長文章摘要放到body
裏,若是直接改aps
內的alert
,那麼8.2之前的設備推送顯示的是文章摘要了。後來咱們想了一個辦法,Notification Service
不是能夠修改推送內容嗎?aps
的alert
仍是保持不變,json增長一個新的title
和body
,Service收到通知以後把json中的title
和body
取出來賦給bestAttemptContent
的title
和body
。ui
{ "aps":{ "alert":"test test", "mutable-content":1 }, "title": "new title", "body": "new body" }
若是通知有attachments,默認狀況下長按通知會顯示圖片或視頻,可是咱們以爲顯示那麼大一個圖片不美觀,並且要有action button,就是下面這種效果,因此要用到Notification Content
。
其實這裏沒有自定義通知的UI,而是直接把這個View隱藏了。Info.plist
中UNNotificationExtensionInitialContentSizeRatio
表示view的初始height/width(其餘屬性參考WWDC),把它設爲0.001(不能設爲0),在viewDidload
中設置self.preferredContentSize = CGSizeZero;
來隱藏view。
這個Extension能夠響應多個category
,而每一個category
能夠註冊本身的action buttons,因此action buttons和customUI view是相互獨立的,不過能夠經過action buttons更新customUI view。
Action buttons默認的行爲會打開APP,由delegate處理響應,使用了Notification Content
後,咱們能夠在Notification Content
直接處理響應而不用打開APP,也能夠forward打開APP由delegate處理。
代碼寫得差很少了,那就開始調試了。Extension調試過程當中有時會遇到Could not attach to process ID
錯誤。
有時重啓Xcode能解決,有時不能解決,這時候有一個方法,這個窗口彈出以後點OK
,接着點Debug > Attach to Process > 你的Extension
,這時候就能捕獲斷點了。
測試過了準備提交TestFlight,結果校驗出錯了。
錯誤信息很明顯,Extension.appex中包含了Frameworks文件夾。若是Extension使用了Cocoapods,Cocoapods會建立這個文件夾,實際沒什麼用。解決辦法就是在Build Phases
最後增長一個Build Phase
,執行一段shell腳本把Frameworks文件夾刪掉。
cd "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/"if [[ -d "Frameworks" ]]; thenrm -fr Frameworksfi