> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-rn-guide-message-privately.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Groups

> Display CometChat iOS UI Kit groups with avatars, member counts, group type indicators, search, filtering, join, and conversation actions.

The `CometChatGroups` component displays a searchable list of all available groups. It shows group names, avatars, member counts, and group type indicators (public/private/password-protected). Users can browse, join, and interact with group conversations.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/jpEUuHUk-hvu4tQT/images/a1ee9071-groups-ded5c6327532be7d5d09c0a491777f9b.png?fit=max&auto=format&n=jpEUuHUk-hvu4tQT&q=85&s=580ad13dd5b1730e53196d4dab65cf9d" alt="CometChatGroups showing a searchable list of groups with avatars, names, member counts, and group type indicators" width="1280" height="800" data-path="images/a1ee9071-groups-ded5c6327532be7d5d09c0a491777f9b.png" />
</Frame>

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "component": "CometChatGroups",
    "package": "CometChatUIKitSwift",
    "import": "import CometChatUIKitSwift\nimport CometChatSDK",
    "description": "Displays a searchable list of all available groups with avatars, names, member counts, and group type indicators.",
    "inherits": "UIViewController",
    "primaryOutput": {
      "callback": "onItemClick",
      "type": "(Group, IndexPath) -> Void"
    },
    "props": {
      "data": {
        "groupsRequestBuilder": {
          "type": "GroupsRequest.GroupsRequestBuilder?",
          "default": "nil",
          "note": "Custom request builder for filtering groups"
        },
        "searchRequestBuilder": {
          "type": "GroupsRequest.GroupsRequestBuilder?",
          "default": "nil",
          "note": "Custom request builder for search"
        }
      },
      "callbacks": {
        "onItemClick": "(Group, IndexPath) -> Void",
        "onItemLongClick": "(Group, IndexPath) -> Void",
        "onBack": "() -> Void",
        "onSelection": "([Group]) -> Void",
        "onSelectedItemProceed": "([Group]) -> Void",
        "onError": "(CometChatException) -> Void",
        "onEmpty": "() -> Void",
        "onLoad": "([Group]) -> Void"
      },
      "visibility": {
        "hideSearch": { "type": "Bool", "default": false },
        "hideNavigationBar": { "type": "Bool", "default": false },
        "hideBackButton": { "type": "Bool", "default": false },
        "hideGroupType": { "type": "Bool", "default": false },
        "hideSectionHeader": { "type": "Bool", "default": false },
        "hideErrorView": { "type": "Bool", "default": false },
        "hideLoadingState": { "type": "Bool", "default": false }
      },
      "selection": {
        "selectionMode": { "type": "SelectionMode", "default": ".none" },
        "selectionLimit": { "type": "Int", "default": 0 },
        "selectedCellCount": { "type": "Int", "default": 0 }
      },
      "styling": {
        "avatarStyle": { "type": "AvatarStyle", "default": "AvatarStyle()" },
        "statusIndicatorStyle": { "type": "StatusIndicatorStyle", "default": "StatusIndicatorStyle()" }
      },
      "viewSlots": {
        "listItemView": "(Group) -> UIView",
        "leadingView": "(Group) -> UIView",
        "titleView": "(Group?) -> UIView",
        "subtitleView": "(Group?) -> UIView",
        "trailingView": "(Group?) -> UIView",
        "emptyStateView": "() -> UIView",
        "errorStateView": "() -> UIView",
        "loadingStateView": "() -> UIView"
      }
    },
    "events": [
      {
        "name": "ccGroupCreated",
        "payload": "Group",
        "description": "Fires when a group is created"
      },
      {
        "name": "ccGroupDeleted",
        "payload": "Group",
        "description": "Fires when a group is deleted"
      },
      {
        "name": "ccGroupMemberJoined",
        "payload": "{ user: User, group: Group }",
        "description": "Fires when a user joins a group"
      },
      {
        "name": "ccGroupMemberLeft",
        "payload": "{ user: User, group: Group }",
        "description": "Fires when a user leaves a group"
      }
    ],
    "sdkListeners": [
      "onGroupMemberJoined",
      "onGroupMemberLeft",
      "onGroupMemberKicked",
      "onGroupMemberBanned",
      "onGroupMemberUnbanned",
      "onGroupMemberScopeChanged",
      "onMemberAddedToGroup"
    ],
    "compositionExample": {
      "description": "Groups list for browsing and joining group conversations",
      "components": ["CometChatGroups", "CometChatMessages"],
      "flow": "User taps on a group → onItemClick fires → Navigate to CometChatMessages with selected group"
    },
    "types": {
      "Group": {
        "guid": "String",
        "name": "String",
        "icon": "String?",
        "membersCount": "Int",
        "groupType": "GroupType",
        "scope": "MemberScope?"
      },
      "GroupType": {
        "public": "Anyone can join",
        "private": "Invite only",
        "password": "Password protected"
      }
    }
  }
  ```
</Accordion>

| Field     | Value                 |
| --------- | --------------------- |
| Component | `CometChatGroups`     |
| Package   | `CometChatUIKitSwift` |
| Inherits  | `UIViewController`    |

***

## Where It Fits

`CometChatGroups` displays all available groups for browsing and joining. It's typically used as a standalone screen or within a tab view controller.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class GroupsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupGroups()
    }
    
    private func setupGroups() {
        let groupsController = CometChatGroups()
        
        // Handle group selection - open group chat
        groupsController.set(onItemClick: { [weak self] group, indexPath in
            self?.openGroupChat(group)
        })
        
        let navController = UINavigationController(rootViewController: groupsController)
        present(navController, animated: true)
    }
    
    private func openGroupChat(_ group: Group) {
        let messagesVC = CometChatMessages()
        messagesVC.set(group: group)
        navigationController?.pushViewController(messagesVC, animated: true)
    }
}
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/jpEUuHUk-hvu4tQT/images/a1ee9071-groups-ded5c6327532be7d5d09c0a491777f9b.png?fit=max&auto=format&n=jpEUuHUk-hvu4tQT&q=85&s=580ad13dd5b1730e53196d4dab65cf9d" alt="CometChatGroups showing integration with navigation controller and group selection handling" width="1280" height="800" data-path="images/a1ee9071-groups-ded5c6327532be7d5d09c0a491777f9b.png" />
</Frame>

***

## Minimal Render

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()
let navController = UINavigationController(rootViewController: groups)
present(navController, animated: true)
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/jpEUuHUk-hvu4tQT/images/a1ee9071-groups-ded5c6327532be7d5d09c0a491777f9b.png?fit=max&auto=format&n=jpEUuHUk-hvu4tQT&q=85&s=580ad13dd5b1730e53196d4dab65cf9d" alt="CometChatGroups showing minimal render with default configuration displaying group list" width="1280" height="800" data-path="images/a1ee9071-groups-ded5c6327532be7d5d09c0a491777f9b.png" />
</Frame>

***

## Filtering

Use `GroupsRequest.GroupsRequestBuilder` to filter which groups appear in the list. The builder pattern allows chaining multiple filter conditions.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

// Create a custom request builder
let groupsRequestBuilder = GroupsRequest.GroupsRequestBuilder(limit: 30)
    .set(joinedOnly: true)

let groups = CometChatGroups(groupsRequestBuilder: groupsRequestBuilder)
```

### Filter Recipes

| Recipe             | Code                                       |
| ------------------ | ------------------------------------------ |
| Joined groups only | `.set(joinedOnly: true)`                   |
| Search by name     | `.set(searchKeyword: "design")`            |
| Filter by tags     | `.set(tags: ["engineering", "marketing"])` |
| Include tag info   | `.set(withTags: true)`                     |
| Limit results      | `GroupsRequestBuilder(limit: 20)`          |

***

## Actions and Events

### Callback Props

#### onItemClick

Fires when a user taps on a group in the list. Use this to open the group chat.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(onItemClick: { [weak self] group, indexPath in
    guard let self = self else { return }
    
    let messagesVC = CometChatMessages()
    messagesVC.set(group: group)
    self.navigationController?.pushViewController(messagesVC, animated: true)
})
```

#### onItemLongClick

Fires when a user long-presses on a group. Use this to show additional options.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(onItemLongClick: { [weak self] group, indexPath in
    guard let self = self else { return }
    
    let alert = UIAlertController(title: group.name, message: nil, preferredStyle: .actionSheet)
    
    alert.addAction(UIAlertAction(title: "View Details", style: .default) { _ in
        // View group details
    })
    
    alert.addAction(UIAlertAction(title: "Leave Group", style: .destructive) { _ in
        // Leave group
    })
    
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
    self.present(alert, animated: true)
})
```

#### onBack

Fires when the back button is pressed.

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()

groups.set(onBack: { [weak self] in
    self?.navigationController?.popViewController(animated: true)
})
```

#### onSelection

Fires when groups are selected in selection mode.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()
groups.selectionMode = .multiple

groups.set(onSelection: { [weak self] selectedGroups in
    print("Selected \(selectedGroups.count) groups")
})
```

#### onSelectedItemProceed

Fires when the user confirms their selection by tapping the proceed/submit button. Use this to handle the final selection action.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()
groups.selectionMode = .multiple
groups.selectionLimit = 5

groups.onSelectedItemProceed = { [weak self] selectedGroups in
    guard let self = self else { return }
    
    // Handle the selected groups
    for group in selectedGroups {
        print("Selected group: \(group.name ?? "")")
    }
    
    // Proceed with the selection
    self.processSelectedGroups(selectedGroups)
}
```

#### onError

Fires when an error occurs while loading groups.

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()

groups.set(onError: { error in
    print("Error loading groups: \(error.errorDescription)")
})
```

#### onEmpty

Fires when the group list is empty.

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()

groups.set(onEmpty: {
    print("No groups found")
})
```

#### onLoad

Fires when groups are successfully loaded.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(onLoad: { groups in
    print("Loaded \(groups.count) groups")
})
```

### Actions Reference

| Method                  | Description                           | Example                 |
| ----------------------- | ------------------------------------- | ----------------------- |
| `set(onItemClick:)`     | Triggered when a group is tapped      | Open group chat         |
| `set(onItemLongClick:)` | Triggered on long press               | Show options menu       |
| `set(onBack:)`          | Triggered when back button is pressed | Custom navigation       |
| `set(onSelection:)`     | Triggered in selection mode           | Multi-select groups     |
| `onSelectedItemProceed` | Triggered when selection is confirmed | Process selected groups |
| `set(onError:)`         | Triggered when an error occurs        | Show error alert        |
| `set(onEmpty:)`         | Triggered when list is empty          | Show empty state        |
| `set(onLoad:)`          | Triggered when groups load            | Analytics tracking      |

### Global UI Events

| Event                 | Fires when            | Payload       |
| --------------------- | --------------------- | ------------- |
| `ccGroupCreated`      | A group is created    | `Group`       |
| `ccGroupDeleted`      | A group is deleted    | `Group`       |
| `ccGroupMemberJoined` | A user joins a group  | `User, Group` |
| `ccGroupMemberLeft`   | A user leaves a group | `User, Group` |

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

class MyViewController: UIViewController, CometChatGroupEventListener {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        CometChatGroupEvents.addListener("my-listener", self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        CometChatGroupEvents.removeListener("my-listener")
    }
    
    func onGroupCreate(group: Group) {
        print("Group created: \(group.name ?? "")")
    }
    
    func onGroupDelete(group: Group) {
        print("Group deleted: \(group.name ?? "")")
    }
    
    func onGroupMemberJoin(joinedUser: User, joinedGroup: Group) {
        print("\(joinedUser.name ?? "") joined \(joinedGroup.name ?? "")")
    }
    
    func onGroupMemberLeave(leftUser: User, leftGroup: Group) {
        print("\(leftUser.name ?? "") left \(leftGroup.name ?? "")")
    }
}
```

### SDK Events (Real-Time, Automatic)

| SDK Listener                | Internal behavior    |
| --------------------------- | -------------------- |
| `onGroupMemberJoined`       | Updates member count |
| `onGroupMemberLeft`         | Updates member count |
| `onGroupMemberKicked`       | Updates member count |
| `onGroupMemberBanned`       | Updates member count |
| `onGroupMemberUnbanned`     | Updates group info   |
| `onGroupMemberScopeChanged` | Updates member scope |
| `onMemberAddedToGroup`      | Updates member count |

***

## Custom View Slots

| Slot               | Signature            | Replaces                |
| ------------------ | -------------------- | ----------------------- |
| `listItemView`     | `(Group) -> UIView`  | Entire group row        |
| `leadingView`      | `(Group) -> UIView`  | Avatar / left section   |
| `titleView`        | `(Group?) -> UIView` | Name / title text       |
| `subtitleView`     | `(Group?) -> UIView` | Member count / subtitle |
| `trailingView`     | `(Group?) -> UIView` | Right side content      |
| `emptyStateView`   | `() -> UIView`       | Empty state display     |
| `errorStateView`   | `() -> UIView`       | Error state display     |
| `loadingStateView` | `() -> UIView`       | Loading state display   |

### listItemView

Replace the entire group row with a custom design.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(listItemView: { group in
    let customView = CustomGroupCell()
    customView.configure(with: group)
    return customView
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/mq8rEbFfi0JjKmkM/images/699f4044-group_list_item-2e7419d48b8185e5effd6cfd19e340b7.png?fit=max&auto=format&n=mq8rEbFfi0JjKmkM&q=85&s=3c44fefe0246a4c003bf420c0fd8f299" alt="CometChatGroups with custom listItemView showing customized group row with avatar, title, member count, and join button" width="1280" height="800" data-path="images/699f4044-group_list_item-2e7419d48b8185e5effd6cfd19e340b7.png" />
</Frame>

You can create a `CustomGroupCell` as a custom `UIView`:

```swift lines theme={null}
import UIKit
import CometChatSDK

class CustomGroupCell: UIView {
    
    private let avatarImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFill
        imageView.layer.cornerRadius = 20
        imageView.clipsToBounds = true
        imageView.backgroundColor = .systemGray5
        return imageView
    }()
    
    private let titleLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = .systemFont(ofSize: 16, weight: .semibold)
        label.textColor = .label
        return label
    }()
    
    private let membersLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = .systemFont(ofSize: 14)
        label.textColor = .secondaryLabel
        return label
    }()
    
    private let joinButton: UIButton = {
        let button = UIButton(type: .system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("JOIN", for: .normal)
        button.titleLabel?.font = .systemFont(ofSize: 12, weight: .bold)
        button.layer.cornerRadius = 12
        button.layer.borderWidth = 1
        button.layer.borderColor = UIColor.systemBlue.cgColor
        return button
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }
    
    private func setupView() {
        addSubview(avatarImageView)
        addSubview(titleLabel)
        addSubview(membersLabel)
        addSubview(joinButton)
        
        NSLayoutConstraint.activate([
            avatarImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            avatarImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
            avatarImageView.widthAnchor.constraint(equalToConstant: 40),
            avatarImageView.heightAnchor.constraint(equalToConstant: 40),
            
            titleLabel.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: 12),
            titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 12),
            titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: joinButton.leadingAnchor, constant: -8),
            
            membersLabel.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: 12),
            membersLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4),
            membersLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12),
            
            joinButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            joinButton.centerYAnchor.constraint(equalTo: centerYAnchor),
            joinButton.widthAnchor.constraint(equalToConstant: 60),
            joinButton.heightAnchor.constraint(equalToConstant: 24)
        ])
    }
    
    func configure(with group: Group) {
        titleLabel.text = group.name
        membersLabel.text = "\(group.membersCount) members"
        
        if let iconURL = group.icon, let url = URL(string: iconURL) {
            URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
                if let data = data, let image = UIImage(data: data) {
                    DispatchQueue.main.async {
                        self?.avatarImageView.image = image
                    }
                }
            }.resume()
        }
        
        let isJoined = group.hasJoined
        joinButton.setTitle(isJoined ? "JOINED" : "JOIN", for: .normal)
        joinButton.setTitleColor(isJoined ? .systemGray : .systemBlue, for: .normal)
        joinButton.layer.borderColor = isJoined ? UIColor.systemGray.cgColor : UIColor.systemBlue.cgColor
    }
}
```

### leadingView

Customize the leading view (avatar area) of a group cell.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(leadingView: { group in
    let view = CustomLeadingView()
    return view
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/2JiXkJ8lq6PmPGlJ/images/7262c876-groupLeading-0104027a201b630d2a22c675886e8f17.png?fit=max&auto=format&n=2JiXkJ8lq6PmPGlJ&q=85&s=1e312b3b26a54d232f812ea741bb28b0" alt="CometChatGroups with custom leadingView showing customized avatar area with icon and join button" width="1280" height="800" data-path="images/7262c876-groupLeading-0104027a201b630d2a22c675886e8f17.png" />
</Frame>

You can create a `CustomLeadingView` as a custom `UIView`:

```swift lines theme={null}
import UIKit

class CustomLeadingView: UIView {

    private let iconImageView: UIImageView = {
        let imageView = UIImageView(image: UIImage(systemName: "person.2.fill"))
        imageView.tintColor = .white
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    private let joinButton: UIButton = {
        let button = UIButton()
        button.setTitle("Join", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .bold)
        button.backgroundColor = .orange
        button.layer.cornerRadius = 8
        return button
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        backgroundColor = .purple
        layer.cornerRadius = 12

        addSubview(iconImageView)
        addSubview(joinButton)

        iconImageView.translatesAutoresizingMaskIntoConstraints = false
        joinButton.translatesAutoresizingMaskIntoConstraints = false
    }
}
```

### titleView

Customize the title view of a group cell.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(titleView: { group in
    let view = CustomTitleView()
    return view
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/21UBnagXOw-XG0Sv/images/adc31834-groupTitle-be2f9110dcb78618c2505a5ab2944b8e.png?fit=max&auto=format&n=21UBnagXOw-XG0Sv&q=85&s=4836472c0608cd435ed588efebaa3344" alt="CometChatGroups with custom titleView showing group name with public badge indicator" width="1280" height="800" data-path="images/adc31834-groupTitle-be2f9110dcb78618c2505a5ab2944b8e.png" />
</Frame>

You can create a `CustomTitleView` as a custom `UIView`:

```swift lines theme={null}
import UIKit

class CustomTitleView: UIView {

    private let titleLabel: UILabel = {
        let label = UILabel()
        label.text = "Artistic Design"
        label.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        label.textColor = .black
        return label
    }()

    private let publicBadge: UIView = {
        let view = UIView()
        view.backgroundColor = .blue
        view.layer.cornerRadius = 10

        let icon = UIImageView(image: UIImage(systemName: "person.3.fill"))
        icon.tintColor = .white
        icon.contentMode = .scaleAspectFit

        let label = UILabel()
        label.text = "Public"
        label.font = UIFont.systemFont(ofSize: 12, weight: .bold)
        label.textColor = .white

        let stackView = UIStackView(arrangedSubviews: [icon, label])
        stackView.spacing = 4
        stackView.alignment = .center
        stackView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(stackView)

        NSLayoutConstraint.activate([
            stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            view.widthAnchor.constraint(equalToConstant: 60),
            view.heightAnchor.constraint(equalToConstant: 20)
        ])
        
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        addSubview(titleLabel)
        addSubview(publicBadge)

        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        publicBadge.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor),
            titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor),

            publicBadge.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 6),
            publicBadge.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }
}
```

### subtitleView

Customize the subtitle area below the group name.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(subtitleView: { group in
    let view = CustomSubtitleView(membersCount: group.membersCount)
    return view
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/OOBJyP9hM0C-rAe_/images/da6d6843-groups_subtitle_view-6e73eb325145dd0670dc66bbf32e41d0.png?fit=max&auto=format&n=OOBJyP9hM0C-rAe_&q=85&s=02d9ae48462056fa6c417d19d92f1d68" alt="CometChatGroups with custom subtitleView showing member count and group description text" width="1280" height="800" data-path="images/da6d6843-groups_subtitle_view-6e73eb325145dd0670dc66bbf32e41d0.png" />
</Frame>

You can create a `CustomSubtitleView` as a custom `UIView`:

```swift lines theme={null}
import UIKit

class CustomSubtitleView: UILabel {
    
    init(membersCount: Int) {
        super.init(frame: .zero)
        self.text = "\(membersCount) members • Group description"
        self.textColor = UIColor.gray
        self.font = UIFont.systemFont(ofSize: 14)
        self.numberOfLines = 1
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
```

### trailingView

Customize the trailing view (right side) of a group cell.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(trailView: { group in
    let view = CustomTrailView()
    return view
})
```

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-docs-rn-guide-message-privately/PrOf0fpV33FkfOMB/images/146de2e1-groupTrail-2cd0321d94d83b2b9194d6182ef5bdde.png?fit=max&auto=format&n=PrOf0fpV33FkfOMB&q=85&s=05f357d07c848cc8ce37dc0599299372" alt="CometChatGroups with custom trailingView showing joined status badge on the right side" width="1280" height="800" data-path="images/146de2e1-groupTrail-2cd0321d94d83b2b9194d6182ef5bdde.png" />
</Frame>

You can create a `CustomTrailView` as a custom `UIView`:

```swift lines theme={null}
import UIKit

class CustomTrailView: UIView {

    private let joinedLabel: UILabel = {
        let label = UILabel()
        label.text = "JOINED"
        label.font = UIFont.systemFont(ofSize: 14, weight: .bold)
        label.textColor = UIColor.purple
        return label
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        backgroundColor = UIColor.purple.withAlphaComponent(0.1)
        layer.cornerRadius = 16

        addSubview(joinedLabel)
        joinedLabel.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            joinedLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
            joinedLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
            widthAnchor.constraint(equalToConstant: 80),
            heightAnchor.constraint(equalToConstant: 32)
        ])
    }
}
```

### loadingStateView

Customize the loading state view displayed while data is being fetched.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

let groups = CometChatGroups()

let loadingIndicator = UIActivityIndicatorView(style: .medium)
loadingIndicator.startAnimating()
groups.set(loadingView: loadingIndicator)
```

### errorStateView

Customize the error state view displayed when an error occurs.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

let groups = CometChatGroups()

let errorLabel = UILabel()
errorLabel.text = "Something went wrong!"
errorLabel.textColor = .red
groups.set(errorView: errorLabel)
```

### emptyStateView

Customize the empty state view displayed when no groups are available.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

let groups = CometChatGroups()

let emptyLabel = UILabel()
emptyLabel.text = "No groups found"
emptyLabel.textColor = .gray
emptyLabel.textAlignment = .center
groups.set(emptyView: emptyLabel)
```

***

## Options

### set(options:)

Define custom swipe options for each group. This method allows you to return an array of `CometChatGroupOption` based on the group object. These options appear when the user swipes on a group cell.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.set(options: { group in
    // Create a custom delete option
    let deleteOption = CometChatGroupOption(
        id: "delete",
        title: "Delete",
        icon: UIImage(systemName: "trash"),
        backgroundColor: .systemRed,
        onClick: { group, section, option, controller in
            // Handle delete action
            print("Delete group: \(group.name ?? "")")
        }
    )
    
    // Create a custom mute option
    let muteOption = CometChatGroupOption(
        id: "mute",
        title: "Mute",
        icon: UIImage(systemName: "bell.slash"),
        backgroundColor: .systemOrange,
        onClick: { group, section, option, controller in
            // Handle mute action
            print("Mute group: \(group.name ?? "")")
        }
    )
    
    return [deleteOption, muteOption]
})
```

### add(options:)

Dynamically add additional swipe options to groups while preserving the default options. This method lets you return additional `CometChatGroupOption` elements that will be appended to the existing options.

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

groups.add(options: { group in
    // Add a custom archive option
    let archiveOption = CometChatGroupOption(
        id: "archive",
        title: "Archive",
        icon: UIImage(systemName: "archivebox"),
        backgroundColor: .systemBlue,
        onClick: { group, section, option, controller in
            // Handle archive action
            print("Archive group: \(group.name ?? "")")
        }
    )
    
    return [archiveOption]
})
```

***

## Data Manipulation Methods

### showJoiningGroupAlert(for:)

Displays an alert dialog when a user attempts to join a password-protected group. This method shows a prompt for the user to enter the group password.

```swift lines theme={null}
public func showJoiningGroupAlert(for group: Group)
```

| Parameter | Type    | Description                          |
| --------- | ------- | ------------------------------------ |
| `group`   | `Group` | The password-protected group to join |

```swift lines theme={null}
import CometChatUIKitSwift
import CometChatSDK

let groups = CometChatGroups()

// Show joining alert for a password-protected group
groups.set(onItemClick: { [weak self] group, indexPath in
    if group.groupType == .password && !group.hasJoined {
        self?.groups.showJoiningGroupAlert(for: group)
    } else {
        // Navigate to group chat
    }
})
```

### hideJoiningGroupAlert(completion:)

Dismisses the joining group alert dialog programmatically. Use this when you need to close the alert without user interaction.

```swift lines theme={null}
public func hideJoiningGroupAlert(completion: (() -> Void)? = nil)
```

| Parameter    | Type            | Description                                          |
| ------------ | --------------- | ---------------------------------------------------- |
| `completion` | `(() -> Void)?` | Optional closure called after the alert is dismissed |

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()

// Hide the joining alert with a completion handler
groups.hideJoiningGroupAlert {
    print("Alert dismissed")
}
```

***

## Styling

### Style Hierarchy

1. Global styles (`CometChatGroups.style`) apply to all instances
2. Instance styles override global for specific instances

### Global Level Styling

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

// Apply global styles that affect all CometChatGroups instances
CometChatGroups.style.backgroundColor = UIColor.systemBackground
CometChatGroups.style.titleColor = UIColor.label
CometChatGroups.style.titleFont = UIFont.systemFont(ofSize: 34, weight: .bold)
CometChatGroups.style.listItemTitleTextColor = UIColor.label
CometChatGroups.style.listItemSubTitleTextColor = UIColor.secondaryLabel

// Custom avatar style
let avatarStyle = AvatarStyle()
avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 8)
CometChatGroups.avatarStyle = avatarStyle
```

### Instance Level Styling

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift

// Create a custom style for a specific instance
var customStyle = GroupsStyle()
customStyle.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 0.97, alpha: 1.0)
customStyle.titleColor = UIColor.darkGray
customStyle.listItemBackground = UIColor.white

let groups = CometChatGroups()
groups.style = customStyle
```

### Key Style Properties

| Property                    | Type      | Default                               | Description                |
| --------------------------- | --------- | ------------------------------------- | -------------------------- |
| `backgroundColor`           | `UIColor` | `CometChatTheme.backgroundColor01`    | Background color           |
| `titleColor`                | `UIColor` | `CometChatTheme.textColorPrimary`     | Navigation title color     |
| `titleFont`                 | `UIFont`  | `CometChatTypography.Heading4.medium` | Navigation title font      |
| `listItemTitleTextColor`    | `UIColor` | `CometChatTheme.textColorPrimary`     | Group name color           |
| `listItemTitleFont`         | `UIFont`  | `CometChatTypography.Heading4.medium` | Group name font            |
| `listItemSubTitleTextColor` | `UIColor` | `CometChatTheme.textColorSecondary`   | Member count color         |
| `listItemSubTitleFont`      | `UIFont`  | `CometChatTypography.Body.regular`    | Member count font          |
| `listItemBackground`        | `UIColor` | `.clear`                              | List item background       |
| `privateGroupBadgeColor`    | `UIColor` | `CometChatTheme.iconColorSecondary`   | Private group badge color  |
| `passwordGroupBadgeColor`   | `UIColor` | `CometChatTheme.iconColorSecondary`   | Password group badge color |

### Customization Matrix

| What to change    | Where     | Property/API              | Example                            |
| ----------------- | --------- | ------------------------- | ---------------------------------- |
| Background color  | Style     | `backgroundColor`         | `UIColor.systemBackground`         |
| Title appearance  | Style     | `titleColor`, `titleFont` | Custom colors and fonts            |
| List item look    | Style     | `listItemBackground`      | `UIColor.white`                    |
| Avatar appearance | Style     | `avatarStyle`             | `AvatarStyle()` with custom radius |
| Group type badges | Style     | `privateGroupBadgeColor`  | Custom badge colors                |
| Hide search       | Property  | `hideSearch`              | `groups.hideSearch = true`         |
| Hide group type   | Property  | `hideGroupType`           | `groups.hideGroupType = true`      |
| Custom row        | View Slot | `set(listItemView:)`      | See Custom View Slots              |

***

## Props

All props are optional. Sorted alphabetically.

### avatarStyle

Customizes the appearance of avatars in group list items.

|         |                 |
| ------- | --------------- |
| Type    | `AvatarStyle`   |
| Default | `AvatarStyle()` |

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()

let avatarStyle = AvatarStyle()
avatarStyle.backgroundColor = UIColor.systemBlue
avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 8)
avatarStyle.borderWidth = 1
avatarStyle.borderColor = UIColor.systemGray4

groups.set(avatarStyle: avatarStyle)
```

### groupsRequestBuilder

Custom request builder for filtering groups.

|         |                                       |
| ------- | ------------------------------------- |
| Type    | `GroupsRequest.GroupsRequestBuilder?` |
| Default | `nil`                                 |

### hideBackButton

Hides the back button in the navigation bar.

|         |         |
| ------- | ------- |
| Type    | `Bool`  |
| Default | `false` |

### hideErrorView

Hides the error state view.

|         |         |
| ------- | ------- |
| Type    | `Bool`  |
| Default | `false` |

### hideGroupType

Hides the public/private/password group type icons.

|         |         |
| ------- | ------- |
| Type    | `Bool`  |
| Default | `false` |

### hideLoadingState

Hides the loading state indicator.

|         |         |
| ------- | ------- |
| Type    | `Bool`  |
| Default | `false` |

### hideNavigationBar

Hides the entire navigation bar.

|         |         |
| ------- | ------- |
| Type    | `Bool`  |
| Default | `false` |

### hideSearch

Hides the search bar.

|         |         |
| ------- | ------- |
| Type    | `Bool`  |
| Default | `false` |

### hideSectionHeader

Hides the alphabetical section headers.

|         |         |
| ------- | ------- |
| Type    | `Bool`  |
| Default | `false` |

### searchRequestBuilder

Custom request builder for search functionality.

|         |                                       |
| ------- | ------------------------------------- |
| Type    | `GroupsRequest.GroupsRequestBuilder?` |
| Default | `nil`                                 |

### selectedCellCount

Returns the count of currently selected groups when in selection mode.

|         |       |
| ------- | ----- |
| Type    | `Int` |
| Default | `0`   |

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()
groups.selectionMode = .multiple

// Get the count of selected groups
let selectedCount = groups.selectedCellCount
print("Selected \(selectedCount) groups")
```

### selectionLimit

Sets the maximum number of groups that can be selected in selection mode. When the limit is reached, further selections are disabled.

|         |                 |
| ------- | --------------- |
| Type    | `Int`           |
| Default | `0` (unlimited) |

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()
groups.selectionMode = .multiple

// Limit selection to 5 groups
groups.selectionLimit = 5

// Handle selection confirmation
groups.onSelectedItemProceed = { selectedGroups in
    print("Selected \(selectedGroups.count) groups")
    
    // Process the selected groups
    for group in selectedGroups {
        print("Group: \(group.name ?? "")")
    }
}
```

### selectionMode

Sets the selection mode for multi-select functionality.

|         |                 |
| ------- | --------------- |
| Type    | `SelectionMode` |
| Default | `.none`         |

### statusIndicatorStyle

Customizes the appearance of group type status indicators.

|         |                          |
| ------- | ------------------------ |
| Type    | `StatusIndicatorStyle`   |
| Default | `StatusIndicatorStyle()` |

```swift lines theme={null}
import CometChatUIKitSwift

let groups = CometChatGroups()

let statusIndicatorStyle = StatusIndicatorStyle()
statusIndicatorStyle.backgroundColor = UIColor.systemGreen
statusIndicatorStyle.borderWidth = 2
statusIndicatorStyle.borderColor = UIColor.white

groups.set(statusIndicatorStyle: statusIndicatorStyle)
```

***

## Events

| Event                 | Payload       | Fires when            |
| --------------------- | ------------- | --------------------- |
| `ccGroupCreated`      | `Group`       | A group is created    |
| `ccGroupDeleted`      | `Group`       | A group is deleted    |
| `ccGroupMemberJoined` | `User, Group` | A user joins a group  |
| `ccGroupMemberLeft`   | `User, Group` | A user leaves a group |

***

## Common Patterns

### Public groups only

```swift lines theme={null}
let publicBuilder = GroupsRequest.GroupsRequestBuilder(limit: 30)
    .set(groupType: .public)

let groups = CometChatGroups()
groups.set(groupsRequestBuilder: publicBuilder)
```

### Joined groups only

```swift lines theme={null}
let joinedBuilder = GroupsRequest.GroupsRequestBuilder(limit: 30)
    .set(joinedOnly: true)

let groups = CometChatGroups()
groups.set(groupsRequestBuilder: joinedBuilder)
```

### Custom empty state with CTA

```swift lines theme={null}
let groups = CometChatGroups()

groups.set(emptyStateView: {
    let emptyView = UIView()
    
    let label = UILabel()
    label.text = "No groups found"
    label.textAlignment = .center
    
    let button = UIButton(type: .system)
    button.setTitle("Create a group", for: .normal)
    
    // Add subviews and constraints...
    return emptyView
})
```

### Hide all chrome — minimal list

```swift lines theme={null}
let groups = CometChatGroups()
groups.hideSearch = true
groups.hideGroupType = true
groups.hideSectionHeader = true
```

### Multi-select groups

```swift lines theme={null}
let groups = CometChatGroups()
groups.selectionMode = .multiple

groups.set(onSelection: { selectedGroups in
    print("Selected \(selectedGroups.count) groups")
})
```

***

## Related Components

* [Messages](/ui-kit/ios/message-list) - Display messages in a group
* [Conversations](/ui-kit/ios/conversations) - List all conversations
* [Users](/ui-kit/ios/users) - List all users
* [Group Members](/ui-kit/ios/group-members) - Manage group members
* [Groups With Messages](/ui-kit/ios/groups) - Combined groups and messages view
