這裏不少文章都是從個人簡書遷移過來的,由於懶得看各類廣告,因此來掘金試試,但願掘金不要淪陷。PS:iOS 相關的工做目前參與比例很小了。git
蘋果在 iOS10 系統推出後,對於以往雜亂的推送處理邏輯進行了統一,推出了 User Notification Framework。對於 iOS7 - iOS9 的推送使用說明請參考文檔:理解iOS的用戶通知。github
本文來介紹 iOS10 以後的推送框架:User Notification Framework,並儘可能對此框架進行全面的介紹,如下全部代碼只適用於 iOS10 及以上的系統。下文全部代碼都可在 Demo 找到。objective-c
#import <UserNotifications/UserNotifications.h>
json
注意:通常註冊通知都在 AppDelegate 的 application:didFinishLaunchingWithOptions: 方法中進行。或者能夠將通知處理業務分離到單獨模塊,並在 AppDelegate 的此方法中調用獨立出的模塊的註冊通知方法。咱們爲了更加直接的說明推送的使用方法,在這裏不作模塊剝離,全部通知處理代碼若無特殊說明,均在 AppDelegate.m 文件中。數組
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 獲取通知中心實例
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 獲取通知類型權限,此接口會觸發應用下載後首次打開時,向用戶申請通知權限
[center requestAuthorizationWithOptions:(UNAuthorizationOptions)(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSLog(@"granted: %d", granted);
if (!error) {
// 爲 notficationCenter 設置代理,以便進行消息接收的回調
center.delegate = self;
// 註冊遠程通知,此方法與 iOS7-9 是同樣的
dispatch_async(dispatch_get_main_queue(), ^{
[application registerForRemoteNotifications];
});
NSLog(@"request authorization success");
} else {
NSLog(@"request authorization failed");
}
}];
}
複製代碼
這裏對 UNAuthorizationOptions 進行簡單介紹:xcode
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"%@",settings);
}];
複製代碼
此接口能夠獲取註冊的通知的詳細信息,如上面註冊通知的信息以下:bash
<
UNNotificationSettings: 0x280f78070;
authorizationStatus: Authorized,
notificationCenterSetting: Enabled,
soundSetting: Enabled,
badgeSetting: Enabled,
lockScreenSetting: Enabled,
carPlaySetting: NotSupported,
criticalAlertSetting: NotSupported,
alertSetting: Enabled,
alertStyle: Banner,
providesAppNotificationSettings: No
>
複製代碼
[[UIApplication sharedApplication] registerForRemoteNotifications];
複製代碼
在第2步驟註冊用戶通知成功的回調中,咱們已經調用了此方法註冊遠程通知。服務器
執行完上述幾個步驟後,運行 demo app,當彈出推送權限確認時選擇容許,便可進行本地與遠程通知的使用(遠程通知須要聯網獲取 deviceToken)。網絡
如今基本的通知包括了標題、副標題以及消息體三部份內容,大體樣式以下:session
根據蘋果的 APNs 文檔來看,iOS10之前的系統是沒有副標題的。下面來看一下如何用新框架來發送簡單的本地通知以及遠程通知。
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"Introduction to User Notification Framework";
content.subtitle = @"WWDC2016 Session 707";
content.body = @"Hi, this is a powerful notification framework for iOS10 and later";
content.badge = @3;
複製代碼
有三種 Trigger:
// 10 秒後提醒,若是將 repeats 設爲 YES,那就是每 10 秒提醒一次
UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:10 repeats:NO];
// 每週一早8點通知
NSDateComponents *components = [[NSDateComponents alloc] init];
components.weekday = 2;
components.hour = 8;
UNCalendarNotificationTrigger *trigger2 = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];
//#import <CoreLocation/CoreLocation.h>
// 到某位置提醒,這個須要參考 CoreLocation 文檔,這裏再也不贅述
CLRegion *region = [[CLRegion alloc] init];
// 此處省略設置 CLRegion 的代碼
UNLocationNotificationTrigger *trigger3 = [UNLocationNotificationTrigger triggerWithRegion:region repeats:NO];
複製代碼
NSString *requestIdentifier = @"TimeIntervalRequest";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier
content:content
trigger:trigger1];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
}];
複製代碼
本地通知的使用基本能夠歸納爲下圖所示的流程:
遠程通知只須要將以下內容消息發送給蘋果的 APNs 服務器便可,至於如何發送 APNs 消息,這裏再也不詳述,能夠 github 搜索 SmartPush。
{
"aps": {
"alert": {
"title": "Introduction to User Notification Framework",
"subtitle": "WWDC2016 Session 707",
"body": "Hi, this is a powerful notification framework for iOS10 and later"
},
"badge": 3,
"sound": "default"
}
}
複製代碼
若是須要接收用戶通知,須要將 [UNUserNotificationCenter currentNotificationCenter] 的 delegate 設置爲實現了 UNUserNotificationCenterDelegate 協議的實例對象(注意須要在 AppDelegate 的 didFinishLaunching 方法結束前設置)。
在本文起始處註冊用戶通知時,咱們將其設置爲了 AppDelegate。
這裏主要有三個回調須要注意:三個均爲 Optional 類型的方法
完整函數定義爲:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;
複製代碼
該方法用於應用在前臺時,接收消息並設置如何展現用戶通知。在這個方法中,能獲取到完整的通知(notification),咱們也能夠進行消息的處理,處理完成後,調用 completionHandler 來告訴系統該如何展現這條通知。應用處於前臺時的彈窗等行爲,在 iOS10 以前是沒有的。
UNNotificationPresentationOptions 可選值有:
例以下述代碼,應用在前臺時,收到通知,會發出提示音以及彈窗
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
}
複製代碼
效果圖以下:
完整函數定義爲:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler;
複製代碼
這個方法會在用戶點擊用戶通知、點擊通知的 Action(以後會講到)後調用,開發者在這裏作消息處理邏輯,response 中含有消息的全部內容,具體內容直接參考 API 接口就好,很清晰。
這裏注意:若是不是經過點擊通知進入了 App,而是直接點擊 App 圖標進入了 App,那麼是收不到回調通知的。
完整函數定義爲:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
複製代碼
使用同一個 requestIdentifier 發送新的本地通知,就能夠覆蓋掉以前的本地通知。咱們能夠在 demo 界面添加一個 button 觸發以下示例代碼:
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"Refreshed Introduction to User Notification Framework";
content.subtitle = @"WWDC2016 Session 707";
content.body = @"Hi, this is a powerful notification framework for iOS10 and later";
content.badge = @2;
UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:10 repeats:NO];
NSString *requestIdentifier = @"TimeIntervalRequest";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier
content:content
trigger:trigger1];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
}];
複製代碼
上面的 requestWithIdentifier 是在 2、發送用戶通知-發送本地通知 中使用的。這裏把原來的 content.title 前面加了 Refreshed,以便於觀察。在收到第一個通知後,點擊應用圖標進入應用,而後點擊設置的 button,觸發上述代碼後,再次進入後臺,等 10s 後能夠看到新推了一條用戶通知,這條用戶通知是更新後的通知,而且原來的通知被覆蓋掉消失了。
須要用到 apns-collapse-id 字段,參考蘋果開發者文檔後,發現這個字段加入到 payload 是沒有做用的,只有經過 HTTP/2 接口向 APNs 發送遠程通知時,放入 header 中。 只要兩個遠程通知使用同一個 apns-collapse-id,那麼第二個通知會覆蓋第一個通知。
這裏沒有作詳細測試,有興趣能夠測一下。
在 iOS8 以後,用戶通知就引入了交互操做,並在 iOS9 中的交互操做中引入了快捷回覆,在 iOS10 以後,交互操做通知獲得了統一與更新。
在上圖中,當通知到達後,使用 3D touch 就能夠更進一步查看消息,此時就能夠看到設置的交互操做,下面介紹如何爲通知添加交互操做。
簡單來講就是建立一個交互操做。能夠指定此交互操做的 id,顯示的內容(title),以及一些可選項。構造函數以下:
+ (instancetype)actionWithIdentifier:(NSString *)identifier title:(NSString *)title options:(UNNotificationActionOptions)options;
複製代碼
identifier 是一個 id,在用戶進行了此交互操做後,能夠在代碼回調方法中拿到此 id,而後能夠根據不一樣 id 進行不一樣邏輯處理;
title 是操做顯示的標題,如上面的示例圖中,Reply、Ignore 就是交互操做的 title;
options 是定製操做的一些選項:
此外,若是你建立的操做須要打開文本框輸入字符,則能夠建立 UNTextInputNotificationAction。下述代碼建立了兩個交互操做:
UNNotificationAction *action = [UNNotificationAction actionWithIdentifier:@"ignore" title:@"Ignore" options:UNNotificationActionOptionDestructive];
UNTextInputNotificationAction *textAction = [UNTextInputNotificationAction actionWithIdentifier:@"reply" title:@"Reply" options:UNNotificationActionOptionNone];
複製代碼
簡單來講就是建立一個交互操做組,將多個交互操做結合在一塊兒。
+ (instancetype)categoryWithIdentifier:(NSString *)identifier actions:(NSArray<UNNotificationAction *> *)actions intentIdentifiers:(NSArray<NSString *> *)intentIdentifiers options:(UNNotificationCategoryOptions)options;
複製代碼
identifier 是一個 id,在用戶進行了此交互操做後,能夠在代碼回調方法中拿到此 id,而後能夠根據不一樣 id 進行不一樣邏輯處理;
actions 是第1步驟建立的交互操做的集合;
intentIdentifiers: 好像與 siri 有關,具體用處不詳,歡迎添加;
options:顯示交互操做時的一些定製選項:
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithArray:@[category]]];
複製代碼
本地通知 只須要在建立的 UNMutableNotificationContent *content 中設置 categoryIdentifier 爲第2步驟中常見的 category 的 identifier 就能夠了:
content.categoryIdentifier = @"actiontest";
複製代碼
遠程通知 在發給 APNs 的 payload 中添加 category 字段,並將其值設置爲第2步驟中建立的 category 的 identifier。如:
{
"aps": {
"alert": {
"title": "Introduction to User Notification Framework",
"subtitle": "WWDC2016 Session 707",
"body": "Hi, this is a powerful notification framework for iOS10 and later"
},
"category": "actiontest",
"badge": 3,
"sound": "default"
}
}
複製代碼
點擊自定義的 action 後,系統會將響應回調到 userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: 方法中,response 參數中包含有 actionIdentifier 屬性,此屬性就是你點擊的 action 的 identifier。此外,response 中的 notification 屬性中含有通知的全部其餘內容。
當左滑屬於某 category 的通知點擊清除時,若是建立 category 時設置的 options 包含 UNNotificationCategoryOptionCustomDismissAction,那麼也會回調到上面的方法,若是沒有設置這個 option,那麼點擊清除時不會有回調。
若是沒有實現 userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: 方法,則點擊 action 時,系統會回調到 iOS8-9 的回調方法,具體參考 iOS8-9 的用戶通知文檔。
若是點擊的是 UNTextInputNotificationAction,那麼系統會彈出鍵盤和輸入框,點擊發送後,會回調到上述方法中,而後在上述方法中能夠拿到輸入的內容:
if ([response.notification.request.content.categoryIdentifier isEqualToString:@"actiontest"]) {
//識別用戶點擊的是哪一個 action
if ([response.actionIdentifier isEqualToString:@"reply"]) {
//假設點擊了輸入內容的 UNTextInputNotificationAction 把 response 強轉類型
UNTextInputNotificationResponse *textResponse = (UNTextInputNotificationResponse*)response;
//獲取輸入內容
NSString *userText = textResponse.userText;
NSLog(@"%@", userText);
} else {
}
複製代碼
# 6、Notification Service Extension
User Notification Framework 新框架添加了 Service Extension 的支持,使得開發者能夠在接收到推送以後與展現推送通知以前對推送通知進行處理和更新。
## 建立 Service Extension
使用 Xcode,**File -> New -> Target -> Notification Service Extension**
[圖片上傳失敗...(image-502a5e-1547470724584)]
添加完成後,工程中會新添加 NotificationService.h/m 文件,打開 NotificationService.m 能夠看到有兩個方法:
注意:調試或運行 Service Extension 須要把 xcode 的 scheme 調整爲你建立的 Service Extension。
### 1.didReceiveNotificationRequest:withContentHandler:
當通知到達後,會回調到此方法,而後在 request 參數中能夠獲取到收到的通知,而後根據需求對 request.content 進行修改,以下代碼只是簡單的更改了一下通知的 title:
複製代碼
(void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy];
// Modify the notification content here... self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title]; self.contentHandler(self.bestAttemptContent); }
你也能夠在用戶通知中添加一些自定義字段,而後在這裏解析,作進一步處理。
注意:
- 最後必定要調用 contentHandler 回調給系統,才能顯示修改的通知內容。
- 在發送通知是,必定要設置 mutable-content 字段爲 1,這個字段說明該推送在接收後可被修改,這個字段決定了系統是否會調用 Notification Service 中的方法。
### 2.serviceExtensionTimeWillExpire
當通知到達後,可使用第一個方法進行處理,可是這個處理是有時間限制的,立即將超時時,會調用此方法,若是上一個方法沒有處理完,此方法能夠做爲備用給一個相對合理的內容。若是第一個方法超時,此方法沒有修改通知,那麼通知會按照原來的內容顯示給用戶。
## 使用 Service Extension 添加通知附件
上一部分是簡單的使用 Service Extension 進行 title 的修改,其實咱們還能夠在通知顯示以前,爲其添加圖片、音頻、視頻附件。下面以圖片爲例。
複製代碼
//代碼位於:didReceiveNotificationRequest:withContentHandler: 方法中
//1. 獲取 url 字符串,APNs aps 字段外的字段會放在 content 的 userInfo 屬性中。 NSString *urlStr = [request.content.userInfo valueForKey:@"attachment"]; NSURL *url=[NSURL URLWithString:urlStr];
//2.建立請求 NSMutableURLRequest *fileRequest=[NSMutableURLRequest requestWithURL:url];
//3.建立會話(這裏使用了一個全局會話)而且啓動任務 NSURLSession *session=[NSURLSession sharedSession];
//4.建立遠程圖片文件存儲位置
NSString *cachePath=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *savePath=[cachePath stringByAppendingPathComponent:@"remote.jpg"];
//5.若是已經有此名字的文件,先刪除(這裏爲了屢次測試) if ([[NSFileManager defaultManager] fileExistsAtPath:savePath]) { [[NSFileManager defaultManager] removeItemAtPath:savePath error:nil]; }
//6.下載圖片文件 NSURLSessionDownloadTask *downloadTask=[session downloadTaskWithRequest:fileRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { if (!error) { //注意location是下載後的臨時保存路徑,須要將它移動到須要保存的位置 NSError *saveError; NSString *cachePath=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *savePath=[cachePath stringByAppendingPathComponent:@"remote.jpg"]; NSLog(@"%@",savePath); NSURL *saveUrl=[NSURL fileURLWithPath:savePath]; [[NSFileManager defaultManager] copyItemAtURL:location toURL:saveUrl error:&saveError]; if (!saveError) { NSLog(@"save sucess."); }else{ NSLog(@"error is :%@",saveError.localizedDescription); }
//7.添加附件
/**
* options 是一個字典,可選項有:
* UNNotificationAttachmentOptionsTypeHintKey: value 是一個包含描述文件的類型統一類型標識符。若是不提供該鍵,根據文件擴展名來肯定其類型
* UNNotificationAttachmentOptionsThumbnailHiddenKey:是一個 BOOL 值,爲 YES 時,縮略圖將隱藏
* UNNotificationAttachmentOptionsThumbnailClippingRectKey:用於剪切矩形的縮略圖
* UNNotificationAttachmentOptionsThumbnailTimeKey:對於視頻附件採用哪一個時間的一幀做爲縮略圖
*/
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"remote-image" URL:saveUrl options:nil error:nil];
self.bestAttemptContent.attachments = @[attachment];
self.contentHandler(content);
}else{
NSLog(@"error is :%@",error.localizedDescription);
self.contentHandler(content);
}
複製代碼
}]; [downloadTask resume];
執行上述操做後,經過向 APNs 發送下面的 payload:
``` json
{
"aps": {
"alert": {
"title": "Introduction to User Notification Framework",
"subtitle": "WWDC2016 Session 707",
"body": "Hi, this is a powerful notification framework for iOS10 and later"
},
"mutable-content": 1,
"category": "msg",
"badge": 3,
"sound": "default"
},
// 這裏 attachment 也能夠取名爲其餘 key,只須要與代碼中獲取 url 的 key 值對應就行了。value 是隨意找的一張網絡圖片的 url
"attachment": "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1536680234778&di=399d12e7871abd75b6d3f217e3d19940&imgtype=0&src=http%3A%2F%2Fe.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F4d086e061d950a7bd63a3bed07d162d9f2d3c988.jpg"
}
複製代碼
而後發送通知,當設備收到通知後,使用 3D touch 後就會看到以下帶圖片附件樣式的通知:
固然,你也可使用本地圖片、語音文件、視頻文件,使用方法相似。使用遠程文件時,必定要先下載到本地,此外,通知對文件類型和大小都有限制,可參考蘋果文檔。
User Notification Framework 新框架還增長了 Content Extension,這個擴展用於徹底自定義推送展現的 UI 界面(這裏指使用 3D touch 打開後的通知 UI 界面)。 同時若是你點擊了 Action,能夠經過自定義邏輯刷新界面,可是自定義的 UI 沒法響應觸摸、點擊、滑動等手勢,只用於展現。
使用 Xcode,File -> New -> Target -> Notification Content Extension
注意:調試或運行 Content Extension 須要把 xcode 的 scheme 調整爲你建立的 Content Extension。
添加 Content Extension 完成後,工程中會新添加 NotificationViewController.h/m、一個 storyboard、一個 Info.plist 文件,能夠在這個 Controller 中自定義 UI(也能夠在 storyboard 中拖拽自定義 UI)。例以下述 demo 代碼建立了三個 label 用於顯示通知:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any required interface initialization here.
[self loadSubviews];
}
- (void)loadSubviews {
_titleLabel = [[UILabel alloc] init];
[_titleLabel setTextColor:[UIColor blackColor]];
[_titleLabel setFont:[UIFont systemFontOfSize:16]];
[self.view addSubview:_titleLabel];
_subTitleLabel = [[UILabel alloc] init];
[_subTitleLabel setTextColor:[UIColor blackColor]];
[_subTitleLabel setFont:[UIFont systemFontOfSize:14]];
[self.view addSubview:_subTitleLabel];
_bodyLabel = [[UILabel alloc] init];
[_bodyLabel setTextColor:[UIColor blackColor]];
[_bodyLabel setFont:[UIFont systemFontOfSize:12]];
[_bodyLabel setNumberOfLines:0];
[self.view addSubview:_bodyLabel];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
_titleLabel.frame = CGRectMake(10, 10, 300, 20);
_subTitleLabel.frame = CGRectMake(10, 40, 300, 20);
_bodyLabel.frame = CGRectMake(10, 60, 300, 50);
}
複製代碼
生成的 NotificationViewController 實現了 UNNotificationContentExtension 協議,這個協議裏有一個接收通知的方法,在這個方法裏面,能夠根據通知的內容填充自定義的通知 UI 界面,示例:
- (void)didReceiveNotification:(UNNotification *)notification {
_titleLabel.text = notification.request.content.title;
_subTitleLabel.text = notification.request.content.subtitle;
_bodyLabel.text = notification.request.content.body;
[_bodyLabel sizeToFit];
}
複製代碼
在 Content Extension 的 Info.plist 中,咱們通常有幾個經常使用屬性設置,以下圖中的 NSExtensionAttributes:
實現了上述代碼以及設置後,運行建立的 Content Extension Scheme,而後發送通知,接收到用戶通知後使用 3D touch 打開通知,就能夠看到自定義的 UI 界面了。
示例通知格式:
{
"aps": {
"alert": {
"title": "Introduction to User Notification Framework",
"subtitle": "WWDC2016 Session 707",
"body": "Hi, this is a powerful notification framework for iOS10 and later"
},
"category": "actiontest",
"badge": 3,
"sound": "default"
}
}
複製代碼
顯示效果:
在 NotificationViewController 中實現 didReceiveNotificationResponse:completionHandler: 方法,當用戶點擊某個 Action 後,就會回調到此方法, 而後此方法的處理方式與上面提到的接收通知和 Action 的處理方式相同。在這裏你能夠更新你本身的 UI,若是這裏沒有實現該方法,則 Action 仍是會回調到 AppDelegate 中的相同方法中。以下代碼,在點擊 Reply action 後,輸入一些字符,最後在回調方法裏,咱們修改了 body label 的內容爲新輸入的字符串:
- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption))completion {
//識別須要被處理的拓展
if ([response.notification.request.content.categoryIdentifier isEqualToString:@"msg"]) {
//識別用戶點擊的是哪一個 action
if ([response.actionIdentifier isEqualToString:@"reply"]) {
//假設點擊了輸入內容的 UNTextInputNotificationAction, 把 response 強轉類型
UNTextInputNotificationResponse *textResponse = (UNTextInputNotificationResponse*)response;
//獲取輸入內容
NSString *userText = textResponse.userText;
NSLog(@"input text: %@", userText);
_bodyLabel.text = userText;
} else if ([response.actionIdentifier isEqualToString:@"ignore"]){
}
}
}
複製代碼