前提条件
请先阅读苹果推送文档
解决方案
-
引入依赖库
#import <UserNotifications/UserNotifications.h>
-
添加通知快捷按钮
- (void)addNotificationCategory { UNNotificationAction *ignoreAction = [UNNotificationAction actionWithIdentifier:@"ignore" title:@"忽略" options:UNNotificationActionOptionNone]; UNNotificationAction *replayAction = [UNTextInputNotificationAction actionWithIdentifier:@"reply" title:@"回复" options:UNNotificationActionOptionNone textInputButtonTitle:@"发送" textInputPlaceholder:@"请输入回复信息"]; UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:@"message" actions:@[ignoreAction, replayAction] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone]; [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObject:category]]; }
-
监听和处理通知代理
[UNUserNotificationCenter currentNotificationCenter].delegate = self; - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { NSString *categoryIdentifier = response.notification.request.content.categoryIdentifier; UNNotificationContent *content = response.notification.request.content; if ([categoryIdentifier isEqualToString:@"message"]) { if ([response.actionIdentifier isEqualToString:@"reply"]) { NSDictionary *userInfo = content.userInfo; NSString *userId = [self getUserIdFromRemotePushInfo:userInfo]; UNTextInputNotificationResponse *tResponse = (UNTextInputNotificationResponse *)response; NSString *userText = tResponse.userText; [self replyMessage:userId content:userText completion:^(BOOL success) { dispatch_async(dispatch_get_main_queue(), ^{ completionHandler(); }); }]; return; } } completionHandler(); }
-
获取消息会话用户id,可以参考融云推送 payload
- (nullable NSString *)getUserIdFromRemotePushInfo:(NSDictionary *)info { NSDictionary *rc = info[@"rc"]; if (![rc isKindOfClass:[NSDictionary class]]) return nil; NSString *userId = rc[@"tId"]; if (![userId isKindOfClass:[NSString class]]) return nil; return userId; }
-
回复消息的实现方式有两种,一种是直接用 IM 建立连接后发送;另一种是调用服务器端接口发送。相对来说第二种方式简单安全,第一种实现起来更复杂、易出错。
客户端方式,以下使用了 IMKit 中的方法:
- (void)replyMessage:(NSString *)toUserId content:(NSString *)content completion:(void(^)(BOOL))completion { NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:@"IM_Token"]; if (!token.length || !toUserId || !content) return !completion?:completion(NO); [RCIM.sharedRCIM initWithAppKey:AppKey option:nil]; RCTextMessage *message = [RCTextMessage messageWithContent:content]; if ([[RCIM sharedRCIM] getConnectionStatus] == ConnectionStatus_Connected) { [[RCIM sharedRCIM] sendMessage:ConversationType_PRIVATE targetId:toUserId content:message pushContent:nil pushData:nil success:^(long messageId) { !completion?:completion(YES); } error:^(RCErrorCode nErrorCode, long messageId) { !completion?:completion(NO); }]; return; } [[RCIM sharedRCIM] connectWithToken:token dbOpened:^(RCDBErrorCode code) { } success:^(NSString *userId) { [[RCIM sharedRCIM] sendMessage:ConversationType_PRIVATE targetId:toUserId content:message pushContent:nil pushData:nil success:^(long messageId) { !completion?:completion(YES); } error:^(RCErrorCode nErrorCode, long messageId) { !completion?:completion(NO); }]; } error:^(RCConnectErrorCode errorCode) { !completion?:completion(NO); }]; }
服务端方式,服务器发送实现请参考文档:
- (void)replyMessage:(NSString *)toUserId content:(NSString *)content completion:(void(^)(BOOL))completion { [network sendMessage:toUserId content:content completion:^(int code){}]; }
-
消息发送。为了支持 Category 事件的触发,需要发送消息时配置推送中的 category 属性,安卓和iOS都需要设置
RCMessage *message = [[RCMessage alloc] initWithType:self.conversationType targetId:self.targetId direction:MessageDirection_SEND content:messageContent]; message.messagePushConfig.iOSConfig.category = @"message"; [[RCIM sharedRCIM] sendMessage:message pushContent:nil pushData:nil successBlock:^(RCMessage *successMessage) { } errorBlock:^(RCErrorCode nErrorCode, RCMessage *errorMessage) { }];
注意:Category 事件触发后,只是调用的部分代码,如果在 AppDelegate 中其它地方初始化和连接时,判断下当前 App 的活跃状态:
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) { [RCIM.sharedRCIM initWithAppKey:AppKey]; }