鍍金池/ 教程/ iOS/ 管理自定義 Long Look 界面
上下文菜單
更新記錄
文本與標(biāo)簽
使用 iOS 技術(shù)
開(kāi)發(fā)您的 Watch 應(yīng)用
Watch 應(yīng)用結(jié)構(gòu)
預(yù)覽概要
界面對(duì)象
UI 概要
Tables
配置 Xcode 項(xiàng)目
圖片
通知要點(diǎn)
設(shè)置
界面導(dǎo)航
管理你的預(yù)覽界面
管理自定義 Long Look 界面

管理自定義 Long Look 界面

自定義 long-look 通知界面包含兩個(gè)獨(dú)立部分,一個(gè)是靜態(tài)的,一個(gè)是動(dòng)態(tài)的。靜態(tài)的界面是必須的,并簡(jiǎn)單的顯示通知的提示信息,它的圖片和文字是在設(shè)計(jì)的時(shí)候就配置的。動(dòng)態(tài)界面是可選的,只是為了讓你有方法能自定義顯示通知內(nèi)容。

當(dāng)你在 storyboard 中創(chuàng)建一個(gè)新的通知界面 controller 的時(shí)候,Xcode 只會(huì)默認(rèn)創(chuàng)建一個(gè)靜態(tài)界面,如果你需要?jiǎng)?chuàng)建動(dòng)態(tài)界面,需要在 storyboard 的通知目錄對(duì)象中選擇 “Has Dynamic Interface” 屬性。(只有在靜態(tài)界面無(wú)法滿足你需要的時(shí),再選擇添加動(dòng)態(tài)界面才是明智的選擇)。圖 16-1 顯示了 storyboard 文件中未修改的靜態(tài)和動(dòng)態(tài)界面場(chǎng)景。靜態(tài)和動(dòng)態(tài)場(chǎng)景都是同一類型的相關(guān)通知,你可以使用通知 category 對(duì)象附加到靜態(tài)場(chǎng)景來(lái)配置。

圖 16-1 靜態(tài)和動(dòng)態(tài)的通知界面

http://wiki.jikexueyuan.com/project/apple-watch-programming-guide/images/notification_static_dynamic_2x.png" alt="靜態(tài)和動(dòng)態(tài)的通知界面" />

當(dāng)合法的通知類型被接受后,WatchKit 會(huì)基于不同的因素來(lái)選擇靜態(tài)或者動(dòng)態(tài)界面。當(dāng)動(dòng)態(tài)頁(yè)面不存在,或者當(dāng)電量不夠,又或者你根本就沒(méi)有明確告訴 WatchKit 顯示動(dòng)態(tài)界面的時(shí)候,WatchKit 會(huì)自動(dòng)顯示靜態(tài)頁(yè)面。在其他情況下,WatchKit 會(huì)顯示你的動(dòng)態(tài)頁(yè)面。在確定顯示動(dòng)態(tài)頁(yè)面后,WatchKit 會(huì)加載合適的 storyboard 資源然后準(zhǔn)備合適的接口。就如圖 16-2 中所描述。 動(dòng)態(tài)界面的加載過(guò)程就跟你應(yīng)用程序中的界面 controller 一樣,只是這個(gè)是通知界面 controller 特定的用來(lái)處理通知負(fù)載數(shù)據(jù)的。

圖 16-2 準(zhǔn)備通知界面

http://wiki.jikexueyuan.com/project/apple-watch-programming-guide/images/notification_process_2x.png" alt="準(zhǔn)備通知界面" />

添加自定義通知界面到你的程序

當(dāng)你為你的目標(biāo)應(yīng)用程序創(chuàng)建 WatchKit 程序時(shí),你需要勾選上 Include Notification Scene 選項(xiàng)來(lái)創(chuàng)建對(duì)應(yīng)通知接口的實(shí)現(xiàn)文件。Xcode 提供了一個(gè)空的 storyboard 場(chǎng)景和一個(gè)用于你通知接口 controller 的自定義子類。如果你在創(chuàng)建的時(shí)候沒(méi)有選中剛才說(shuō)的那個(gè)選項(xiàng),而你又需要?jiǎng)?chuàng)建通知接口,則需要手動(dòng)自己添加。

手動(dòng)添加通知接口:拖一個(gè)通知接口 controller 對(duì)象到你的 storyboard 文件。新的接口僅僅只是包含了靜態(tài)的頁(yè)面控制器,為了創(chuàng)建動(dòng)態(tài)接口,你必須執(zhí)行以下配置步驟:

配置動(dòng)態(tài)通知接口controller

  1. 在你的項(xiàng)目中,創(chuàng)建一個(gè)新的 WKUserNotificationInterfaceController子類。
    創(chuàng)建新的資源文件并將其添加到你的 WatchKit 拓展目標(biāo),然后給你的類一個(gè)合適的名字以區(qū)別于其他通知接口 controller。

  2. 勾選通知目錄中得 Has Dynamic Interface,這一步將添加動(dòng)態(tài)場(chǎng)景到你的 storyboard 文件。

  3. 設(shè)置你動(dòng)態(tài)通知界面 controller 為在第一步創(chuàng)建的類。

應(yīng)用程序可能有多個(gè)通知界面,你可以使用目錄(categories)來(lái)區(qū)分。再你得 storyboard 文件中,使用 Notification Category 對(duì)象指定 category 名字來(lái)關(guān)聯(lián)不同的場(chǎng)景。WatchKit 使用 category 值來(lái)決定在運(yùn)行時(shí)加載哪個(gè)場(chǎng)景。如果進(jìn)來(lái)的通知沒(méi)有 category,WatchKit 則加載 category 名為 default 的。更多關(guān)于如何指定通知的 category,請(qǐng)見(jiàn) “Configuring the Category of a Custom Interface”。

配置自定義界面的 Category

每個(gè)通知接口必須有指定的通知 category,這樣才能告訴 Apple Watch 什么時(shí)候使用。發(fā)送進(jìn)來(lái)的通知可以在負(fù)載數(shù)據(jù)中包含一個(gè) category 鍵,值則你自己定義。Apple Watch 使用 category 來(lái)決定顯示哪個(gè)通知場(chǎng)景。如果進(jìn)來(lái)的通知沒(méi)有包含 category 字符串,Apple Watch 顯示配置時(shí)的默認(rèn)通知界面。

指定你通知接口的通知類型,在你的 storyboard 中選擇 “Notification Category” 對(duì)象并選擇 Attributes 檢查框,如圖 16-3 所示。在檢查框中得 Name 字段里輸入 category 的名字。同時(shí)你也能在這個(gè)框中設(shè)置你自定義界面的 sash 顏色和標(biāo)題文字。

圖 16-3 配置通知類型信息

http://wiki.jikexueyuan.com/project/apple-watch-programming-guide/images/notification_type_config_2x.png" alt="配置通知類型信息" />

當(dāng)生成遠(yuǎn)程通知時(shí),你的服務(wù)器通過(guò)在負(fù)載數(shù)據(jù)的 aps 字典里包含一個(gè) category 鍵來(lái)指定通知類型。對(duì)于本地通知,你可以通過(guò) UILocalNotification 對(duì)象的 category 屬性的值來(lái)指定。

注意
category 字符串同樣也能定義哪些活動(dòng)按鈕(如果有的話)被追加到通知界面的最后,獲取更多關(guān)于支持自定義活動(dòng)的信息,請(qǐng)見(jiàn) Adding Action Buttons to Notifications

配置靜態(tài)通知界面

使用靜態(tài)通知界面來(lái)定義一個(gè)簡(jiǎn)單的自定義的通知界面,靜態(tài)界面的目的是為了在你 WatchKit 拓展的事件中提供一個(gè)回調(diào)接口,WatchKit 拓展是無(wú)法及時(shí)配置動(dòng)態(tài)界面的,以下是創(chuàng)建一個(gè)靜態(tài)界面的規(guī)則:

  • 所欲的圖像必須位于 WatchKit 應(yīng)用程序包。

  • 界面不能包含控件,表格,地圖或者其他互動(dòng)元素。

  • 界面的 notificationAlertLabel 出口必須連接到一個(gè) label,這個(gè) label 的內(nèi)容設(shè)置為通知的提示信息。對(duì)于所有其他標(biāo)簽的文字都不要改變,而要再你的 storyboard 文件中指定。

圖 16-4 展示了在一個(gè)日歷程序中自定義通知界面的靜態(tài)和動(dòng)態(tài)場(chǎng)景。通知箭頭指向了靜態(tài)場(chǎng)景,這個(gè)場(chǎng)景中包含了一個(gè)自定義 icon 和兩個(gè)label。在靜態(tài)界面中,label 包含了一個(gè)字符串 <message>,它就是跟 notificationAlertLabel 出口相關(guān)的,因此它會(huì)在運(yùn)行時(shí)收到通知的提示消息。

圖 16-4 一個(gè)單一通知類型的靜態(tài)和動(dòng)態(tài)場(chǎng)景

http://wiki.jikexueyuan.com/project/apple-watch-programming-guide/images/notification_design_2x.png" alt="一個(gè)單一通知類型的靜態(tài)和動(dòng)態(tài)場(chǎng)景" />

配置動(dòng)態(tài)通知界面

一個(gè)動(dòng)態(tài)通知界面可以為用戶提供更加豐富的體驗(yàn)。使用動(dòng)態(tài)界面,你可以顯示更多而不僅僅只是提示消息。你可以放置更多的信息,配置更多的 label,顯示動(dòng)態(tài)生成的內(nèi)容等等。

實(shí)現(xiàn)動(dòng)態(tài)的通知界面需要?jiǎng)?chuàng)建一個(gè) WKUserNotificationInterfaceController 的子類。當(dāng)一個(gè)合適類型的通知過(guò)來(lái)時(shí),這個(gè)子類的實(shí)現(xiàn)就是用來(lái)響應(yīng)它的。

設(shè)計(jì)你的動(dòng)態(tài)界面

配置你得動(dòng)態(tài)界面就像其他界面 controller 場(chǎng)景,包括在你的子類中引用的 label,image 和其他場(chǎng)景中的對(duì)象。然后使用這些在運(yùn)行時(shí)配置場(chǎng)景內(nèi)容。點(diǎn)擊通知頁(yè)面啟動(dòng)應(yīng)用程序,所以通知界面不應(yīng)該包含交互控制。

  • 多為你的界面使用 label,image,group 和 separator(分離器)。

  • 你可以可以在你的界面中包含 table 和 map。

  • 不要包含 button,switch 或者其他交互控制。

在運(yùn)行時(shí)配置你的動(dòng)態(tài)界面

當(dāng)一個(gè)合適類型的通知到達(dá)時(shí),WatchKit 從你的 storyboard 中選擇合適的場(chǎng)景顯示并告訴你的 WatchKit 拓展初始化對(duì)應(yīng) WKUserNotificationInterfaceController 子類。圖 16-5 展示了 WatchKit 需要準(zhǔn)備你界面的步驟,在初始化通知界面 controller 之后,WatchKit 使用 didReceiveRemoteNotification:withCompletion: 或者 didReceiveLocalNotification:withCompletion: 方法來(lái)發(fā)送有效負(fù)載數(shù)據(jù),然后你使用負(fù)載數(shù)據(jù)來(lái)配置你通知界面的其他部分,然后調(diào)用設(shè)置完成處理程序塊讓 WatchKit 知道你的界面已經(jīng)準(zhǔn)備好了。

圖 16-5 配置動(dòng)態(tài)通知界面

http://wiki.jikexueyuan.com/project/apple-watch-programming-guide/images/notification_event_cycle_2x.png" alt="配置動(dòng)態(tài)通知界面" />

總是使用 didReceiveRemoteNotification:withCompletion: 或者 didReceiveLocalNotification:withCompletion: 方法來(lái)配置你的通知界面,當(dāng)實(shí)現(xiàn)了其中任意方法后,已經(jīng)配置的界面提供的處理程序會(huì)盡快執(zhí)行完成。如果等得太久,Apple Watch 會(huì)嘗試放棄顯示你的動(dòng)態(tài)界面而以顯示靜態(tài)界面來(lái)代替。

清單 16-1 展示了 didReceiveRemoteNotification:withCompletion: 方法實(shí)現(xiàn)的示例。這個(gè)方法是通過(guò)一個(gè)虛構(gòu)的日歷程序,發(fā)送一個(gè)新的會(huì)議邀請(qǐng)遠(yuǎn)程通知。該方法從遠(yuǎn)程通知的負(fù)載數(shù)據(jù)中提取數(shù)據(jù)并利用該數(shù)據(jù)來(lái)設(shè)置通知界面上的 label 值。為簡(jiǎn)單起見(jiàn),該示例假定服務(wù)器總是為每個(gè) key 都包含了一個(gè)合適的值。但你自己的代碼應(yīng)該做一些必要的錯(cuò)誤檢查以保證這些負(fù)載數(shù)據(jù)是有效的。在配置完 label 之后,則調(diào)用處理程序讓 WatchKit 知道自定義的界面以及準(zhǔn)備好可以顯示了。

清單 16-1 在一個(gè)遠(yuǎn)程通知里配置自定義界面

// Standard remote notification payload keys.
NSString* apsKeyString = @"aps";
NSString* titleKeyString = @"title";

// Payload keys that are specific to the app.
NSString* customDataKey = @"cal";
NSString* invitationDateKey = @"date";
NSString* invitationLocationKey = @"loc";
NSString* invitationNotesKey = @"note";

- (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void(^)(WKUserNotificationInterfaceType interface)) completionHandler {
    // Get the aps dictionary from the payload.
    NSDictionary* apsDict = [remoteNotification objectForKey:apsKeyString];

    // Retrieve the title of the invitation.
    NSString* titleString = [apsDict objectForKey:titleKeyString];
    [self.titleLabel setText:titleString];

    // Extract the date and time from the custom section of the payload.
    // The date/time information is stored as the number of seconds since 1970.
    NSDictionary* customDataDict = [remoteNotification objectForKey:customDataKey];
    NSNumber* dateValue = [customDataDict objectForKey:invitationDateKey];
    NSDate* inviteDate = [NSDate dateWithTimeIntervalSince1970:[dateValue doubleValue]];

    // Format the date and time strings.
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

    // Call a custom method to get the localized date format string for the user.
    // The default date format string is "EEE, MMM d".
    dateFormatter.dateFormat = [self dateFormatForCurrentUser];
    NSString *formattedDateString = [dateFormatter stringFromDate:inviteDate];

    // Call a custom method to get the localized time format string for the user.
    // The default time format string is "h:mm a".
    dateFormatter.dateFormat = [self timeFormatForCurrentUser];
    NSString *formattedTimeString = [dateFormatter stringFromDate:inviteDate];

    // Set the date and time in the corresponding labels.
    [self.dateLabel setText:formattedDateString];
    [self.timeLabel setText:formattedTimeString];

    // Set the location of the meeting.
    NSString* locationString = [customDataDict objectForKey:invitationLocationKey];
    [self.locationLabel setText:locationString];

    // Set the invitation's notes (if any).
    NSString* notesString = [customDataDict objectForKey:invitationNotesKey];
    [self.notesLabel setText:notesString];

    // Tell WatchKit to display the custom interface.
    completionHandler(WKUserNotificationInterfaceTypeCustom);
}

在調(diào)用完成處理代碼塊時(shí),如果你希望 WatchKit 顯示靜態(tài)界面,那就指定 WKUserNotificationInterfaceTypeDefault 常量。

注意
通知界面的文字僅僅只支持系統(tǒng)指定的文字字體,如果你需要顯示其他字體,最好是將文字嵌入圖片中,然后顯示那張圖片。

測(cè)試你自定義界面

當(dāng)你已經(jīng)準(zhǔn)備好在模擬器上測(cè)試你的動(dòng)態(tài)界面時(shí),為你的通知界面創(chuàng)建一個(gè)自定義運(yùn)行計(jì)劃,如果你還沒(méi)有這么做的話。當(dāng)你配置界面時(shí),指定一個(gè)你希望發(fā)送到你的界面并包含測(cè)試數(shù)據(jù)的 JSON 文件。Xcode 會(huì)為指定的數(shù)據(jù)提供自定義的 JSON 文件。

更多關(guān)于設(shè)置運(yùn)行計(jì)劃并配置你的數(shù)據(jù)的信息,請(qǐng)見(jiàn) The Build, Run, Debug Process。

上一篇:通知要點(diǎn)下一篇:更新記錄