Skip to main content
The CometChatGroupMembers component displays all members of a group with their roles (owner, admin, participant). It supports member management actions like kick, ban, and role changes.

Prerequisites

Before using this component:
  1. Initialize CometChat UI Kit
  2. Log in a user
  3. Have a valid Group object

Basic Usage

import UIKit
import CometChatUIKitSwift
import CometChatSDK

class GroupDetailViewController: UIViewController {
    
    var group: Group!
    
    func showGroupMembers() {
        let groupMembers = CometChatGroupMembers(group: group)
        let nav = UINavigationController(rootViewController: groupMembers)
        present(nav, animated: true)
    }
}

Production-Ready Implementation

Complete example with member actions and navigation:
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class GroupMembersViewController: UIViewController {
    
    var group: Group!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupGroupMembers()
    }
    
    private func setupGroupMembers() {
        let groupMembers = CometChatGroupMembers(group: group)
        
        // Handle member tap
        groupMembers.set(onItemClick: { [weak self] member, indexPath in
            self?.showMemberProfile(member)
        })
        
        // Handle long press for options
        groupMembers.set(onItemLongClick: { [weak self] member, indexPath in
            self?.showMemberOptions(member)
        })
        
        // Handle errors
        groupMembers.set(onError: { error in
            print("Error: \(error.errorDescription)")
        })
        
        // Handle empty state
        groupMembers.set(onEmpty: {
            print("No members found")
        })
        
        // Handle back button
        groupMembers.set(onBack: { [weak self] in
            self?.navigationController?.popViewController(animated: true)
        })
        
        navigationController?.pushViewController(groupMembers, animated: true)
    }
    
    private func showMemberProfile(_ member: GroupMember) {
        // Open user profile or start direct chat
        let messages = CometChatMessages()
        messages.set(user: member)
        navigationController?.pushViewController(messages, animated: true)
    }
    
    private func showMemberOptions(_ member: GroupMember) {
        let alert = UIAlertController(title: member.name, message: nil, preferredStyle: .actionSheet)
        
        alert.addAction(UIAlertAction(title: "Message", style: .default) { [weak self] _ in
            self?.showMemberProfile(member)
        })
        
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        present(alert, animated: true)
    }
}

Filter Members

Use GroupMembersRequestBuilder to filter the member list:
// Filter by scope (admin, moderator, participant)
let requestBuilder = GroupMembersRequest.GroupMembersRequestBuilder(guid: group.guid)
    .set(limit: 20)
    .set(scopes: ["admin", "moderator"])

let groupMembers = CometChatGroupMembers(
    group: group,
    groupMembersRequestBuilder: requestBuilder
)
// Search members
let searchBuilder = GroupMembersRequest.GroupMembersRequestBuilder(guid: group.guid)
    .set(searchKeyword: "john")

let groupMembers = CometChatGroupMembers(
    group: group,
    groupMembersRequestBuilder: searchBuilder
)

Actions Reference

MethodDescription
set(onItemClick:)Member tapped
set(onItemLongClick:)Member long-pressed
set(onBack:)Back button pressed
set(onSelection:)Selection changed (multi-select mode)
set(onError:)Error occurred
set(onEmpty:)No members found
set(onLoad:)Members loaded

Hide UI Elements

let groupMembers = CometChatGroupMembers(group: group)

groupMembers.hideSearch = true              // Hide search bar
groupMembers.hideUserStatus = true          // Hide online/offline status
groupMembers.hideKickMemberOption = true    // Hide kick option
groupMembers.hideBanMemberOption = true     // Hide ban option
groupMembers.hideScopeChangeOption = true   // Hide role change option
groupMembers.hideNavigationBar = true       // Hide navigation bar
groupMembers.hideBackIcon = true            // Hide back button

Styling

Quick Styling

// Global styling
CometChatGroupMembers.style.titleColor = UIColor(hex: "#6851D6")
CometChatGroupMembers.style.titleFont = .systemFont(ofSize: 20, weight: .bold)
CometChatGroupMembers.style.backgroundColor = .systemBackground

// Custom avatar style
let avatarStyle = AvatarStyle()
avatarStyle.backgroundColor = UIColor(hex: "#FBAA75")
avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 20)
CometChatGroupMembers.avatarStyle = avatarStyle

Instance Styling

let groupMembersStyle = GroupMembersStyle()
groupMembersStyle.titleColor = UIColor(hex: "#F76808")
groupMembersStyle.backgroundColor = .white
groupMembersStyle.listItemTitleTextColor = .black

let groupMembers = CometChatGroupMembers(group: group)
groupMembers.style = groupMembersStyle

Custom Views

Custom List Item

Replace the entire member row with your own design:
let groupMembers = CometChatGroupMembers(group: group)

groupMembers.set(listItemView: { member in
    let customView = MemberRowView()
    customView.configure(with: member!)
    return customView
})
// MemberRowView.swift
import UIKit
import CometChatSDK
import CometChatUIKitSwift

class MemberRowView: UIView {
    
    private let avatar = CometChatAvatar(image: UIImage())
    private let nameLabel = UILabel()
    private let roleButton = UIButton(type: .system)
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupUI() {
        avatar.translatesAutoresizingMaskIntoConstraints = false
        avatar.layer.cornerRadius = 20
        
        nameLabel.translatesAutoresizingMaskIntoConstraints = false
        nameLabel.font = .systemFont(ofSize: 16, weight: .semibold)
        
        roleButton.translatesAutoresizingMaskIntoConstraints = false
        roleButton.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium)
        roleButton.setTitleColor(.white, for: .normal)
        roleButton.backgroundColor = .systemPurple
        roleButton.layer.cornerRadius = 10
        roleButton.contentEdgeInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8)
        
        addSubview(avatar)
        addSubview(nameLabel)
        addSubview(roleButton)
        
        NSLayoutConstraint.activate([
            avatar.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            avatar.centerYAnchor.constraint(equalTo: centerYAnchor),
            avatar.widthAnchor.constraint(equalToConstant: 40),
            avatar.heightAnchor.constraint(equalToConstant: 40),
            
            nameLabel.leadingAnchor.constraint(equalTo: avatar.trailingAnchor, constant: 12),
            nameLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
            
            roleButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            roleButton.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }
    
    func configure(with member: GroupMember) {
        nameLabel.text = member.name ?? ""
        avatar.setAvatar(avatarUrl: member.avatar ?? "", with: member.name ?? "")
        roleButton.setTitle(member.scope.rawValue.capitalized, for: .normal)
    }
}

Custom Subtitle View

Customize the subtitle area below the member name:
groupMembers.setSubtitleView(subtitleView: { member in
    let label = UILabel()
    label.font = .systemFont(ofSize: 12)
    label.textColor = .secondaryLabel
    
    let date = Date(timeIntervalSince1970: Double(member!.joinedAt))
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    label.text = "Joined: \(formatter.string(from: date))"
    
    return label
})

Custom Tail View

Add custom content on the right side of each row:
groupMembers.setTailView(tailView: { member in
    let badge = UILabel()
    badge.text = member!.scope.rawValue.capitalized
    badge.font = .systemFont(ofSize: 10, weight: .semibold)
    badge.textColor = UIColor(hex: "#6852D6")
    badge.backgroundColor = UIColor(hex: "#EDEAFA")
    badge.textAlignment = .center
    badge.layer.cornerRadius = 10
    badge.clipsToBounds = true
    return badge
})

Custom Swipe Options

Add custom actions when swiping on a member:
let deleteOption = CometChatGroupMemberOption(
    id: "delete",
    title: "Remove",
    icon: UIImage(systemName: "trash"),
    backgroundColor: .systemRed,
    onClick: { member, group, section, option, controller in
        print("Remove \(member.name ?? "")")
        // Implement remove logic
    }
)

let messageOption = CometChatGroupMemberOption(
    id: "message",
    title: "Message",
    icon: UIImage(systemName: "message"),
    backgroundColor: .systemBlue,
    onClick: { member, group, section, option, controller in
        let messages = CometChatMessages()
        messages.set(user: member)
        controller.navigationController?.pushViewController(messages, animated: true)
    }
)

groupMembers.setOptions(options: { group, member in
    return [messageOption, deleteOption]
})

Custom Menu Buttons

Add buttons to the navigation bar:
let addButton = UIBarButtonItem(
    image: UIImage(systemName: "person.badge.plus"),
    style: .plain,
    target: self,
    action: #selector(addMemberTapped)
)

groupMembers.set(menus: [addButton])

@objc func addMemberTapped() {
    // Show add member screen
    let addMembers = CometChatAddMembers(group: group)
    navigationController?.pushViewController(addMembers, animated: true)
}

Listen for Events

React to member changes in your app:
class MyViewController: UIViewController, CometChatGroupEventListener {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        CometChatGroupEvents.addListener("member-listener", self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        CometChatGroupEvents.removeListener("member-listener")
    }
    
    // Member kicked
    func onGroupMemberKick(kickedUser: User, kickedGroup: Group) {
        print("\(kickedUser.name ?? "") was kicked")
    }
    
    // Member banned
    func onGroupMemberBan(bannedUser: User, bannedGroup: Group) {
        print("\(bannedUser.name ?? "") was banned")
    }
    
    // Member role changed
    func onGroupMemberChangeScope(updatedBy: User, updatedUser: User, scopeChangedTo: CometChat.MemberScope, scopeChangedFrom: CometChat.MemberScope, group: Group) {
        print("\(updatedUser.name ?? "") is now \(scopeChangedTo)")
    }
}

Style Properties

PropertyDescription
backgroundColorBackground color
titleColorTitle text color
titleFontTitle font
listItemTitleTextColorMember name color
listItemTitleFontMember name font
listItemSubTitleTextColorSubtitle color
listItemBackgroundRow background color
separatorColorRow separator color

Troubleshooting

IssueSolution
Empty member listVerify group GUID is correct
Actions not showingCheck user has admin/owner permissions
Custom views not appearingEnsure views have proper constraints
Events not firingVerify listener is added before actions