Documentation Index Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Enable the current group owner to delegate ownership to another member using CometChat’s UIKit for iOS.
Overview
The Transfer Group Ownership feature provides a modal interface where the group owner can:
See a list of current group members (excluding themselves)
Select exactly one member to become the new owner
Trigger the ownership transfer API call
Automatically exit the group after successful transfer
Prerequisites
Before implementing ownership transfer, ensure you have:
Completed Getting Started setup
CometChat UIKit v5+ installed via CocoaPods or Swift Package Manager
CometChatSDK and CometChatUIKitSwift integrated
User logged in with CometChatUIKit.login()
UINavigationController or modal presentation flow set up
Group context (GUID) available when invoking the transfer screen
Components
Component Description TransferOwnershipSubclass of CometChatGroupMembers enabling single selection mode viewModel.groupMembersData source array of GroupMember objects onSelectedItemProceedClosure invoked when user confirms selection CometChat.transferGroupOwnershipAPI call to delegate group ownership spinnerViewUIActivityIndicatorView showing loading stateleaveGroupCallbackCallback to perform group exit after transfer
Integration Steps
Step 1: Present Transfer Ownership Screen
Show the ownership transfer UI modally:
import UIKit
import CometChatSDK
import CometChatUIKitSwift
class GroupDetailsViewController : UIViewController {
var group: Group ?
func showTransferOwnership ( for group : Group) {
// Initialize transfer ownership view controller
let transferVC = TransferOwnership ()
transferVC. set ( group : group)
// Set callback for after transfer completes
transferVC. leaveGroupCallback = { [ weak self ] in
self ? . leaveGroup ()
}
// Present modally with navigation
let nav = UINavigationController ( rootViewController : transferVC)
present (nav, animated : true )
}
private func leaveGroup () {
// Handle leaving group after ownership transfer
navigationController ? . popToRootViewController ( animated : true )
}
}
File reference: GroupDetailsViewController.swift
Restrict selection to one member and capture selection:
import UIKit
import CometChatUIKitSwift
import CometChatSDK
class TransferOwnership : CometChatGroupMembers {
var leaveGroupCallback: (() -> Void ) ?
private let spinnerView: UIActivityIndicatorView = {
let spinner = UIActivityIndicatorView ( style : . medium )
spinner. hidesWhenStopped = true
return spinner
}()
override func viewDidLoad () {
// Enable single selection mode
selectionMode = . single
super . viewDidLoad ()
// Set navigation title
title = "OWNERSHIP_TRANSFER" . localize ()
// Handle member selection
onSelectedItemProceed = { [ weak self ] users in
if let newOwner = users. first as? GroupMember {
self ? . transferOwnership ( to : newOwner)
}
}
}
}
File reference: TransferOwnership.swift
Step 3: Load and Filter Member List
Exclude the current owner from the selectable list:
override func reloadData () {
super . reloadData ()
viewModel. reload = { [ weak self ] in
guard let self = self else { return }
// Get current user's UID
let currentUID = CometChat. getLoggedInUser () ? . uid
// Remove current owner from the list
self . viewModel . groupMembers . removeAll { $0 . uid == currentUID }
DispatchQueue. main . async {
// Update UI state
self . removeLoadingView ()
self . removeErrorView ()
self . reload ()
// Show empty state if no eligible members
if self .viewModel.groupMembers. isEmpty {
self . showEmptyView ()
}
}
}
}
File reference: TransferOwnership.swift
Call the API, emit event, and exit the group:
func transferOwnership ( to member : GroupMember) {
// Show loading indicator
addSpinnerView ()
let uid = member. uid ?? ""
let guid = viewModel. group . guid
CometChat. transferGroupOwnership ( UID : uid, GUID : guid) { [ weak self ] successMessage in
DispatchQueue. main . async {
guard let self = self else { return }
// Update local group state
self . viewModel . group . owner = uid
// Emit ownership changed event for other components
CometChatGroupEvents. ccOwnershipChanged (
group : self . viewModel . group ,
newOwner : member
)
// Execute leave group callback
self . leaveGroupCallback ? ()
// Hide loading and dismiss
self . removeSpinnerView ()
self . dismiss ( animated : true )
}
} onError : { [ weak self ] error in
DispatchQueue. main . async {
self ? . removeSpinnerView ()
// Show error alert
let alert = UIAlertController (
title : "Transfer Failed" ,
message : error ? . errorDescription ?? "Unable to transfer ownership" ,
preferredStyle : . alert
)
alert. addAction ( UIAlertAction ( title : "OK" , style : . default ))
self ? . present (alert, animated : true )
}
}
}
File reference: TransferOwnership.swift
Step 5: Manage Loading State
Provide visual feedback during network calls:
func addSpinnerView () {
// Start spinner animation
spinnerView. startAnimating ()
// Replace right bar button with spinner
navigationItem. rightBarButtonItem = UIBarButtonItem ( customView : spinnerView)
}
func removeSpinnerView () {
// Stop spinner animation
spinnerView. stopAnimating ()
// Remove spinner from navigation bar
navigationItem. rightBarButtonItem = nil
}
File reference: TransferOwnership.swift
Complete Implementation
Here’s the complete TransferOwnership class:
import UIKit
import CometChatUIKitSwift
import CometChatSDK
class TransferOwnership : CometChatGroupMembers {
// MARK: - Properties
var leaveGroupCallback: (() -> Void ) ?
private let spinnerView: UIActivityIndicatorView = {
let spinner = UIActivityIndicatorView ( style : . medium )
spinner. hidesWhenStopped = true
return spinner
}()
// MARK: - Lifecycle
override func viewDidLoad () {
selectionMode = . single
super . viewDidLoad ()
title = "Transfer Ownership"
onSelectedItemProceed = { [ weak self ] users in
if let newOwner = users. first as? GroupMember {
self ? . transferOwnership ( to : newOwner)
}
}
}
// MARK: - Data Loading
override func reloadData () {
super . reloadData ()
viewModel. reload = { [ weak self ] in
guard let self = self else { return }
let currentUID = CometChat. getLoggedInUser () ? . uid
self . viewModel . groupMembers . removeAll { $0 . uid == currentUID }
DispatchQueue. main . async {
self . removeLoadingView ()
self . removeErrorView ()
self . reload ()
if self .viewModel.groupMembers. isEmpty {
self . showEmptyView ()
}
}
}
}
// MARK: - Transfer Ownership
func transferOwnership ( to member : GroupMember) {
addSpinnerView ()
let uid = member. uid ?? ""
let guid = viewModel. group . guid
CometChat. transferGroupOwnership ( UID : uid, GUID : guid) { [ weak self ] _ in
DispatchQueue. main . async {
guard let self = self else { return }
self . viewModel . group . owner = uid
CometChatGroupEvents. ccOwnershipChanged (
group : self . viewModel . group ,
newOwner : member
)
self . leaveGroupCallback ? ()
self . removeSpinnerView ()
self . dismiss ( animated : true )
}
} onError : { [ weak self ] error in
DispatchQueue. main . async {
self ? . removeSpinnerView ()
self ? . showError (error)
}
}
}
// MARK: - Loading State
func addSpinnerView () {
spinnerView. startAnimating ()
navigationItem. rightBarButtonItem = UIBarButtonItem ( customView : spinnerView)
}
func removeSpinnerView () {
spinnerView. stopAnimating ()
navigationItem. rightBarButtonItem = nil
}
// MARK: - Error Handling
private func showError ( _ error : CometChatException ? ) {
let alert = UIAlertController (
title : "Transfer Failed" ,
message : error ? . errorDescription ?? "Unable to transfer ownership" ,
preferredStyle : . alert
)
alert. addAction ( UIAlertAction ( title : "OK" , style : . default ))
present (alert, animated : true )
}
}
Customization Options
Title Text
Replace localization key with custom string:
title = "Select New Owner"
Spinner Style
Adjust spinnerView.style and color using CometChatTheme:
spinnerView. style = . large
spinnerView. color = CometChatTheme. palette . primary
Error Handling
Customize error alerts in the onError closure:
let alert = UIAlertController (
title : "Oops!" ,
message : "Could not transfer ownership. Please try again." ,
preferredStyle : . alert
)
alert. addAction ( UIAlertAction ( title : "Retry" , style : . default ) { [ weak self ] _ in
self ? . transferOwnership ( to : member)
})
alert. addAction ( UIAlertAction ( title : "Cancel" , style : . cancel ))
present (alert, animated : true )
Edge Cases
Scenario Handling Empty member list Show an informative empty state when no eligible members exist Network failures Disable proceed button until connection restores Blocked members Exclude or disable blocked users from selection
Error Handling
Error Type Solution Transfer failures Present UIAlertController with retry option Unexpected states Ensure removeSpinnerView() always executes in defer
Feature Matrix
Feature Method / Component File(s) Launch transfer flow showTransferOwnership(for:)GroupDetailsViewController.swiftSingle-member selection selectionMode = .singleTransferOwnership.swiftFilter out current owner reloadData() overrideTransferOwnership.swiftExecute API transfer CometChat.transferGroupOwnership()TransferOwnership.swiftShow/hide loading indicator addSpinnerView(), removeSpinnerView()TransferOwnership.swift
Groups Display and manage groups
Group Members View and manage group membership
Group Chat Guide Complete group management guide