| name | cometchat-ios-push |
| description | Set up push notifications for CometChat iOS apps — APNs configuration, token registration, and notification handling. |
| license | MIT |
| compatibility | CometChatUIKitSwift ^5; iOS 13+ |
| metadata | {"author":"CometChat","version":"3.0.0","tags":"chat cometchat ios push notifications apns"} |
Ground truth: CometChatUIKitSwift ~> 5 (+ CometChatCallsSDK ~> 5) — Pods/SPM .swiftinterface + ui-kit/ios. Official docs: https://www.cometchat.com/docs/notifications/overview · Docs MCP: claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp (or fetch the URL directly without MCP). Verify symbols against the installed package/source before relying on them.
Purpose
This skill teaches how to set up push notifications for CometChat iOS apps, including APNs configuration, token registration, and handling incoming notifications.
1. Prerequisites
Before setting up push notifications:
- Apple Developer Account — Required for APNs certificates
- CometChat Dashboard Access — To configure push notification settings
- Physical iOS Device — Push notifications don't work on simulators
2. APNs Certificate Setup
Step 1: Create APNs Key (Recommended)
- Go to Apple Developer Portal
- Navigate to Certificates, Identifiers & Profiles → Keys
- Click + to create a new key
- Enter a name (e.g., "CometChat Push Key")
- Enable Apple Push Notifications service (APNs)
- Click Continue → Register
- Download the
.p8 file (you can only download it once!)
- Note the Key ID and your Team ID
Step 2: Configure CometChat Dashboard
- Go to CometChat Dashboard
- Select your app
- Navigate to Notifications → Push Notifications
- Select iOS tab
- Upload your
.p8 file
- Enter your Key ID and Team ID
- Select the environment (Development/Production)
- Save the configuration
3. Xcode Project Configuration
Enable Push Notifications Capability
- Open your project in Xcode
- Select your target
- Go to Signing & Capabilities
- Click + Capability
- Add Push Notifications
- Add Background Modes and enable:
- Remote notifications
- Voice over IP (if using calls)
Update Info.plist
Add the following to your Info.plist:
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
<string>voip</string>
</array>
4. Code Implementation
AppDelegate Setup
import UIKit
import UserNotifications
import CometChatUIKitSwift
import CometChatSDK
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
initializeCometChat()
requestNotificationPermission()
application.registerForRemoteNotifications()
return true
}
private func initializeCometChat() {
let uiKitSettings = UIKitSettings()
.set(appID: "YOUR_APP_ID")
.set(authKey: "YOUR_AUTH_KEY")
.set(region: "us")
.subscribePresenceForAllUsers()
.build()
CometChatUIKit(uiKitSettings: uiKitSettings) { result in
switch result {
case .success:
print("CometChat initialized")
case .failure(let error):
()
}
}
}
() {
center .current()
center.delegate
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error
granted {
()
} error error {
()
}
}
}
(
: ,
:
) {
token deviceToken.map { (format: , ) }.joined()
()
registerPushToken(token)
}
(
: ,
:
) {
()
}
( : ) {
.registerPushToken(
pushToken: token,
platform: .,
providerId:
) { success
()
} onError: { error
()
}
}
( : () -> ) {
.unregisterPushToken {
completion()
} onError: {
completion()
}
}
(
: ,
: [: ],
: () ->
) {
()
messageData userInfo[] [: ] {
handleCometChatNotification(messageData)
}
completionHandler(.newData)
}
( : [: ]) {
type data[] { }
type {
:
handleChatNotification(data)
:
handleCallNotification(data)
:
()
}
}
( : [: ]) {
senderUID data[] { }
.main.async {
.default.post(
name: .openConversation,
object: ,
userInfo: [: senderUID]
)
}
}
( : [: ]) {
()
}
}
: {
(
: ,
: ,
: () ->
) {
completionHandler([.banner, .sound, .badge])
}
(
: ,
: ,
: () ->
) {
userInfo response.notification.request.content.userInfo
messageData userInfo[] [: ] {
handleCometChatNotification(messageData)
}
completionHandler()
}
}
. {
openConversation .()
}
Handle Notification Navigation
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(handleOpenConversation(_:)),
name: .openConversation,
object: nil
)
}
@objc private func handleOpenConversation(_ notification: Notification) {
guard let uid = notification.userInfo?["uid"] as? String else { return }
CometChat.getUser(UID: uid) { [weak self] user in
guard let user = user else { return }
DispatchQueue.main.async {
let messagesVC = MessagesVC()
messagesVC.set(user: user)
self?.navigationController.pushViewController(messagesVC, animated: )
}
} onError: { error
()
}
}
{
.default.removeObserver()
}
}
5. VoIP Push Notifications (for Calls)
Import PushKit
import PushKit
Register for VoIP
class AppDelegate: UIResponder, UIApplicationDelegate {
var voipRegistry: PKPushRegistry?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
registerForVoIPPush()
return true
}
private func registerForVoIPPush() {
voipRegistry = PKPushRegistry(queue: .main)
voipRegistry?.delegate = self
voipRegistry?.desiredPushTypes = [.voIP]
}
}
extension AppDelegate: PKPushRegistryDelegate {
func pushRegistry(
_ registry: PKPushRegistry,
didUpdate pushCredentials: PKPushCredentials,
for type: PKPushType
) {
token pushCredentials.token.map { (format: , ) }.joined()
()
.registerPushToken(
pushToken: token,
platform: .,
providerId:
) { success
()
} onError: { error
()
}
}
(
: ,
: ,
: ,
: () ->
) {
()
callData payload.dictionaryPayload[] [: ] {
handleIncomingCall(callData)
}
completion()
}
( : [: ]) {
}
}
6. UIKitSettings with Push Tokens
You can also pass tokens during initialization:
let uiKitSettings = UIKitSettings()
.set(appID: "YOUR_APP_ID")
.set(authKey: "YOUR_AUTH_KEY")
.set(region: "us")
.set(deviceToken: apnsToken)
.set(voipToken: voipToken)
.subscribePresenceForAllUsers()
.build()
CometChatUIKit(uiKitSettings: uiKitSettings) { result in
}
7. Notification Service Extension
For rich notifications with images and custom content:
Create Extension
- In Xcode, go to File → New → Target
- Select Notification Service Extension
- Name it (e.g., "NotificationService")
Implement Extension
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
guard let bestAttemptContent = bestAttemptContent else {
contentHandler(request.content)
return
}
if let messageData = request.content.userInfo["message"] as? [String: Any] {
customizeNotification(bestAttemptContent, with: messageData)
}
contentHandler(bestAttemptContent)
}
private func customizeNotification(
_ : ,
: [: ]
) {
senderName data[] {
content.title senderName
}
messageText data[] {
content.body messageText
}
imageURL data[] ,
url (string: imageURL) {
downloadAndAttachImage(url, to: content)
}
}
( : , : ) {
task .shared.downloadTask(with: url) { localURL, , error
localURL localURL, error { }
tempDir .default.temporaryDirectory
tempFile tempDir.appendingPathComponent(().uuidString )
.default.moveItem(at: localURL, to: tempFile)
attachment (identifier: , url: tempFile) {
content.attachments [attachment]
}
.contentHandler(content)
}
task.resume()
}
() {
contentHandler contentHandler, bestAttemptContent bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
8. Badge Count Management
Update Badge Count
UIApplication.shared.applicationIconBadgeNumber = unreadCount
UIApplication.shared.applicationIconBadgeNumber = 0
Sync with CometChat Unread Count
func updateBadgeCount() {
CometChat.getUnreadMessageCount { unread in
var totalUnread = 0
for (_, count) in unread {
totalUnread += count as? Int ?? 0
}
DispatchQueue.main.async {
UIApplication.shared.applicationIconBadgeNumber = totalUnread
}
} onError: { error in
print("Error getting unread count: \(error?.errorDescription ?? "")")
}
}
9. Testing Push Notifications
Using Terminal
curl -v \
--header "apns-topic: com.yourapp.bundleid" \
--header "apns-push-type: alert" \
--header "authorization: bearer $JWT_TOKEN" \
--data '{"aps":{"alert":"Test message"}}' \
--http2 \
https://api.push.apple.com/3/device/$DEVICE_TOKEN
Using CometChat Dashboard
- Go to CometChat Dashboard
- Navigate to Users
- Select a user
- Click Send Push Notification
- Enter a test message
- Send
Troubleshooting
| Issue | Solution |
|---|
| Token not registering | Ensure device is physical, not simulator |
| Notifications not received | Check APNs certificate in dashboard |
| Badge not updating | Check notification permissions |
| VoIP not working | Ensure VoIP capability is enabled |
| Notifications delayed | Check APNs environment (dev vs prod) |
Best Practices
- Always request permission before registering for notifications
- Handle token refresh — tokens can change
- Test on real devices — simulators don't support push
- Use Notification Service Extension for rich notifications
- Implement proper deep linking for notification taps
- Clear badge count when user opens the app
- Handle both foreground and background notifications