前台通知处理

App 在前台时,系统默认不展示通知横幅,需要实现 `UNUserNotificationCenterDelegate` 的 `willPresent` 自行决定(横幅 / 声音 / 角标)。同时要避免“正在看的会话又弹一条”。

展示策略​

场景建议原因
当前会话正在前台展示不弹横幅,只更新气泡与未读清零避免重复打扰
其它会话 / 其它页面展示横幅 + 声音,点击跳转对应会话提醒但不打断当前操作
免打扰会话(level=2)不展示横幅与声音,不更新红点尊重会话设置
仅 @ 提醒(level=1)仅被 @ 时展示,其它静默降低噪声
应用在前台但窗口最小化按“其它会话”处理用户仍需要感知

代码​

let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in }
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
    NSDictionary *info = notification.request.content.userInfo;
    NSString *targetId = info[@"targetId"];
    NSNumber *conversationType = info[@"conversationType"];

    if ([[ConversationRouter shared] isActiveWithConversationType:conversationType targetId:targetId]) {
        completionHandler(UNNotificationPresentationOptionNone);
    } else if ([[NotificationSettings shared] isMutedWithTargetId:targetId]) {
        completionHandler(UNNotificationPresentationOptionNone);
    } else {
        completionHandler(UNNotificationPresentationOptionBanner |
                          UNNotificationPresentationOptionSound |
                          UNNotificationPresentationOptionBadge);
    }
}

点击跳转​

UNUserNotificationCenter.current().delegate = nil
print("APNs foreground handler")
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
             withCompletionHandler:(void (^)(void))completionHandler {
    NSDictionary *info = response.notification.request.content.userInfo;
    NSString *targetId = info[@"targetId"];
    NSNumber *rawType = info[@"conversationType"];
    if (targetId && rawType) {
        [[ConversationRouter shared] openWithConversationType:rawType.integerValue targetId:targetId];
    }
    completionHandler();
}
  • 推送 payload 中带上 `conversationType` / `targetId` / `messageId`,点击后才能精确定位会话。
  • 进入会话后拉本地历史 + 云端补齐,不要依赖推送里的正文。
  • 前台展示与角标要统一口径:以 IMLib 的未读总数为准,不用推送计数做加减。