{"id":"082cd0d6-b17f-4a68-a8b5-628884ea9ccd","shortId":"9V8auS","kind":"skill","title":"cometchat-ios-placement","tagline":"WHERE to put CometChat in your iOS app — navigation patterns, tab bars, modals, and embedded views.","description":"## Purpose\n\nThis skill teaches WHERE to place CometChat components in your iOS app. It covers navigation patterns, tab bar integration, modal presentations, and embedded views for different use cases.\n\n---\n\n## 1. Navigation Stack Pattern\n\nThe most common pattern for messaging apps. Push conversations onto a navigation stack.\n\n### Basic Navigation Flow\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  UINavigationController                                      │\n│  ┌─────────────────────────────────────────────────────────┐│\n│  │  CometChatConversations                                 ││\n│  │  ┌─────────────────────────────────────────────────────┐││\n│  │  │  Conversation 1                                     │││\n│  │  │  Conversation 2  ──────────────────────────────────►│││\n│  │  │  Conversation 3                                     │││\n│  │  └─────────────────────────────────────────────────────┘││\n│  └─────────────────────────────────────────────────────────┘│\n└─────────────────────────────────────────────────────────────┘\n                              │\n                              ▼\n┌─────────────────────────────────────────────────────────────┐\n│  MessagesViewController (pushed)                             │\n│  ┌─────────────────────────────────────────────────────────┐│\n│  │  CometChatMessageHeader                                 ││\n│  ├─────────────────────────────────────────────────────────┤│\n│  │  CometChatMessageList                                   ││\n│  │                                                         ││\n│  │                                                         ││\n│  ├─────────────────────────────────────────────────────────┤│\n│  │  CometChatMessageComposer                               ││\n│  └─────────────────────────────────────────────────────────┘│\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Implementation (UIKit)\n\n```swift\n// SceneDelegate.swift\nfunc scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {\n    guard let windowScene = (scene as? UIWindowScene) else { return }\n    \n    let window = UIWindow(windowScene: windowScene)\n    \n    // Create conversations list\n    let conversations = CometChatConversations()\n    conversations.set(onItemClick: { [weak conversations] conversation, _ in\n        let messagesVC = MessagesVC()  // your own VC composing CometChatMessageHeader + List + Composer; see cometchat-ios-components § 12\n        if let user = conversation.conversationWith as? User {\n            messagesVC.set(user: user)\n        } else if let group = conversation.conversationWith as? Group {\n            messagesVC.set(group: group)\n        }\n        conversations?.navigationController?.pushViewController(messagesVC, animated: true)\n    })\n    \n    // Wrap in navigation controller\n    let navController = UINavigationController(rootViewController: conversations)\n    \n    window.rootViewController = navController\n    self.window = window\n    window.makeKeyAndVisible()\n}\n```\n\n### Implementation (SwiftUI)\n\n```swift\nimport SwiftUI\nimport CometChatUIKitSwift\nimport CometChatSDK\n\nstruct ChatNavigationView: View {\n    @State private var selectedConversation: Conversation?\n    @State private var showMessages = false\n    \n    var body: some View {\n        NavigationStack {\n            ConversationsListView(selectedConversation: $selectedConversation)\n                .navigationDestination(isPresented: $showMessages) {\n                    if let conversation = selectedConversation {\n                        MessagesView(conversation: conversation)\n                    }\n                }\n                .onChange(of: selectedConversation) { newValue in\n                    showMessages = newValue != nil\n                }\n        }\n    }\n}\n\nstruct ConversationsListView: UIViewControllerRepresentable {\n    @Binding var selectedConversation: Conversation?\n    \n    func makeUIViewController(context: Context) -> CometChatConversations {\n        let conversations = CometChatConversations()\n        conversations.onItemClick = { conversation, _ in\n            selectedConversation = conversation\n        }\n        return conversations\n    }\n    \n    func updateUIViewController(_ uiViewController: CometChatConversations, context: Context) {}\n}\n```\n\n---\n\n## 2. Tab Bar Pattern\n\nFor apps where chat is one of several main features.\n\n### Tab Layout\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│                                                             │\n│                    Content Area                             │\n│                                                             │\n│                                                             │\n│                                                             │\n├─────────────────────────────────────────────────────────────┤\n│  ┌─────┐  ┌─────┐  ┌─────┐  ┌─────┐  ┌─────┐              │\n│  │Home │  │Chats│  │Users│  │Groups│ │Calls│              │\n│  └─────┘  └─────┘  └─────┘  └─────┘  └─────┘              │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Implementation (UIKit)\n\n```swift\nimport UIKit\nimport CometChatUIKitSwift\nimport CometChatSDK\n\nclass MainTabBarController: UITabBarController {\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        setupTabs()\n    }\n    \n    private func setupTabs() {\n        // Home tab (your existing content)\n        let homeVC = HomeViewController()\n        homeVC.tabBarItem = UITabBarItem(\n            title: \"Home\",\n            image: UIImage(systemName: \"house\"),\n            selectedImage: UIImage(systemName: \"house.fill\")\n        )\n        \n        // Chats tab\n        let chatsVC = createChatsTab()\n        let chatsNav = UINavigationController(rootViewController: chatsVC)\n        chatsNav.tabBarItem = UITabBarItem(\n            title: \"Chats\",\n            image: UIImage(systemName: \"message\"),\n            selectedImage: UIImage(systemName: \"message.fill\")\n        )\n        \n        // Users tab\n        let usersVC = CometChatUsers()\n        usersVC.set(onItemClick: { [weak self] user, _ in\n            self?.openMessages(with: user)\n        })\n        let usersNav = UINavigationController(rootViewController: usersVC)\n        usersNav.tabBarItem = UITabBarItem(\n            title: \"Users\",\n            image: UIImage(systemName: \"person.2\"),\n            selectedImage: UIImage(systemName: \"person.2.fill\")\n        )\n        \n        // Groups tab\n        let groupsVC = CometChatGroups()\n        groupsVC.set(onItemClick: { [weak self] group, _ in\n            self?.openMessages(with: group)\n        })\n        let groupsNav = UINavigationController(rootViewController: groupsVC)\n        groupsNav.tabBarItem = UITabBarItem(\n            title: \"Groups\",\n            image: UIImage(systemName: \"person.3\"),\n            selectedImage: UIImage(systemName: \"person.3.fill\")\n        )\n        \n        var tabs: [UIViewController] = [\n            UINavigationController(rootViewController: homeVC),\n            chatsNav,\n            usersNav,\n            groupsNav\n        ]\n        \n        // Calls tab - only available if CometChatCallsSDK is installed\n        #if canImport(CometChatCallsSDK)\n        let callsVC = CometChatCallLogs()\n        let callsNav = UINavigationController(rootViewController: callsVC)\n        callsNav.tabBarItem = UITabBarItem(\n            title: \"Calls\",\n            image: UIImage(systemName: \"phone\"),\n            selectedImage: UIImage(systemName: \"phone.fill\")\n        )\n        tabs.append(callsNav)\n        #endif\n        \n        viewControllers = tabs\n    }\n    \n    private func createChatsTab() -> CometChatConversations {\n        let conversations = CometChatConversations()\n        conversations.set(onItemClick: { [weak self] conversation, _ in\n            if let user = conversation.conversationWith as? User {\n                self?.openMessages(with: user)\n            } else if let group = conversation.conversationWith as? Group {\n                self?.openMessages(with: group)\n            }\n        })\n        return conversations\n    }\n    \n    private func openMessages(with user: User) {\n        let messagesVC = MessagesVC()  // your own VC composing CometChatMessageHeader + List + Composer; see cometchat-ios-components § 12\n        messagesVC.set(user: user)\n        messagesVC.hidesBottomBarWhenPushed = true\n        \n        if let navController = selectedViewController as? UINavigationController {\n            navController.pushViewController(messagesVC, animated: true)\n        }\n    }\n    \n    private func openMessages(with group: Group) {\n        let messagesVC = MessagesVC()  // your own VC composing CometChatMessageHeader + List + Composer; see cometchat-ios-components § 12\n        messagesVC.set(group: group)\n        messagesVC.hidesBottomBarWhenPushed = true\n        \n        if let navController = selectedViewController as? UINavigationController {\n            navController.pushViewController(messagesVC, animated: true)\n        }\n    }\n}\n```\n\n### Implementation (SwiftUI)\n\n```swift\nstruct MainTabView: View {\n    @State private var selectedTab = 0\n    \n    var body: some View {\n        TabView(selection: $selectedTab) {\n            HomeView()\n                .tabItem {\n                    Label(\"Home\", systemImage: \"house\")\n                }\n                .tag(0)\n            \n            ChatNavigationView()\n                .tabItem {\n                    Label(\"Chats\", systemImage: \"message\")\n                }\n                .tag(1)\n            \n            UsersNavigationView()\n                .tabItem {\n                    Label(\"Users\", systemImage: \"person.2\")\n                }\n                .tag(2)\n            \n            GroupsNavigationView()\n                .tabItem {\n                    Label(\"Groups\", systemImage: \"person.3\")\n                }\n                .tag(3)\n            \n            CallsNavigationView()\n                .tabItem {\n                    Label(\"Calls\", systemImage: \"phone\")\n                }\n                .tag(4)\n        }\n    }\n}\n```\n\n---\n\n## 3. Modal Presentation Pattern\n\nFor apps where chat is a secondary feature, presented modally.\n\n### Modal Layout\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  Your App Content                                           │\n│                                                             │\n│  ┌─────────────────────────────────────────────────────────┐│\n│  │  Product Details                                        ││\n│  │                                                         ││\n│  │  ┌─────────────────────────────────────────────────────┐││\n│  │  │  [Chat with Seller]  ◄─────────────────────────────│││\n│  │  └─────────────────────────────────────────────────────┘││\n│  └─────────────────────────────────────────────────────────┘│\n└─────────────────────────────────────────────────────────────┘\n                              │\n                              ▼ (modal presentation)\n┌─────────────────────────────────────────────────────────────┐\n│  ┌─────────────────────────────────────────────────────────┐│\n│  │  [X]  Chat with John                                    ││\n│  ├─────────────────────────────────────────────────────────┤│\n│  │                                                         ││\n│  │  Messages                                               ││\n│  │                                                         ││\n│  ├─────────────────────────────────────────────────────────┤│\n│  │  Composer                                               ││\n│  └─────────────────────────────────────────────────────────┘│\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Implementation (UIKit)\n\n```swift\nclass ProductDetailViewController: UIViewController {\n    \n    var sellerUID: String?\n    \n    @IBAction func chatWithSellerTapped(_ sender: UIButton) {\n        guard let sellerUID = sellerUID else { return }\n        \n        // Fetch the seller user\n        CometChat.getUser(UID: sellerUID) { [weak self] user in\n            guard let user = user else { return }\n            \n            DispatchQueue.main.async {\n                let messagesVC = MessagesVC()  // your own VC composing CometChatMessageHeader + List + Composer; see cometchat-ios-components § 12\n                messagesVC.set(user: user)\n                \n                let navController = UINavigationController(rootViewController: messagesVC)\n                navController.modalPresentationStyle = .pageSheet\n                \n                // Add close button\n                messagesVC.navigationItem.leftBarButtonItem = UIBarButtonItem(\n                    barButtonSystemItem: .close,\n                    target: self,\n                    action: #selector(self?.dismissChat)\n                )\n                \n                self?.present(navController, animated: true)\n            }\n        } onError: { error in\n            print(\"Error fetching user: \\(error?.errorDescription ?? \"\")\")\n        }\n    }\n    \n    @objc private func dismissChat() {\n        dismiss(animated: true)\n    }\n}\n```\n\n### Implementation (SwiftUI)\n\n```swift\nstruct ProductDetailView: View {\n    let sellerUID: String\n    @State private var showChat = false\n    @State private var seller: User?\n    \n    var body: some View {\n        VStack {\n            // Product details...\n            \n            Button(\"Chat with Seller\") {\n                fetchSellerAndShowChat()\n            }\n            .buttonStyle(.borderedProminent)\n        }\n        .sheet(isPresented: $showChat) {\n            if let seller = seller {\n                NavigationStack {\n                    MessagesView(user: seller)\n                        .toolbar {\n                            ToolbarItem(placement: .navigationBarLeading) {\n                                Button(\"Close\") {\n                                    showChat = false\n                                }\n                            }\n                        }\n                }\n            }\n        }\n    }\n    \n    private func fetchSellerAndShowChat() {\n        CometChat.getUser(UID: sellerUID) { user in\n            DispatchQueue.main.async {\n                self.seller = user\n                self.showChat = true\n            }\n        } onError: { error in\n            print(\"Error: \\(error?.errorDescription ?? \"\")\")\n        }\n    }\n}\n```\n\n---\n\n## 4. Floating Button Pattern\n\nFor support chat or quick access to messages.\n\n### Floating Button Layout\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  Your App Content                                           │\n│                                                             │\n│                                                             │\n│                                                             │\n│                                                             │\n│                                                             │\n│                                                             │\n│                                                     ┌─────┐ │\n│                                                     │ 💬  │ │\n│                                                     └─────┘ │\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Implementation (UIKit)\n\n```swift\nclass FloatingChatButton: UIButton {\n    \n    private var unreadCount: Int = 0 {\n        didSet {\n            updateBadge()\n        }\n    }\n    \n    private lazy var badgeLabel: UILabel = {\n        let label = UILabel()\n        label.backgroundColor = .systemRed\n        label.textColor = .white\n        label.font = .systemFont(ofSize: 12, weight: .bold)\n        label.textAlignment = .center\n        label.layer.cornerRadius = 10\n        label.clipsToBounds = true\n        label.isHidden = true\n        return label\n    }()\n    \n    override init(frame: CGRect) {\n        super.init(frame: frame)\n        setupButton()\n    }\n    \n    required init?(coder: NSCoder) {\n        super.init(coder: coder)\n        setupButton()\n    }\n    \n    private func setupButton() {\n        backgroundColor = .systemBlue\n        layer.cornerRadius = 28\n        layer.shadowColor = UIColor.black.cgColor\n        layer.shadowOffset = CGSize(width: 0, height: 4)\n        layer.shadowRadius = 8\n        layer.shadowOpacity = 0.3\n        \n        setImage(UIImage(systemName: \"message.fill\"), for: .normal)\n        tintColor = .white\n        \n        addSubview(badgeLabel)\n        badgeLabel.translatesAutoresizingMaskIntoConstraints = false\n        NSLayoutConstraint.activate([\n            badgeLabel.topAnchor.constraint(equalTo: topAnchor, constant: -5),\n            badgeLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 5),\n            badgeLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 20),\n            badgeLabel.heightAnchor.constraint(equalToConstant: 20)\n        ])\n    }\n    \n    private func updateBadge() {\n        badgeLabel.isHidden = unreadCount == 0\n        badgeLabel.text = unreadCount > 99 ? \"99+\" : \"\\(unreadCount)\"\n    }\n    \n    func setUnreadCount(_ count: Int) {\n        unreadCount = count\n    }\n}\n\n// Usage in a view controller\nclass MainViewController: UIViewController {\n    \n    private lazy var chatButton: FloatingChatButton = {\n        let button = FloatingChatButton()\n        button.addTarget(self, action: #selector(openChat), for: .touchUpInside)\n        return button\n    }()\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        setupFloatingButton()\n    }\n    \n    private func setupFloatingButton() {\n        view.addSubview(chatButton)\n        chatButton.translatesAutoresizingMaskIntoConstraints = false\n        NSLayoutConstraint.activate([\n            chatButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20),\n            chatButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20),\n            chatButton.widthAnchor.constraint(equalToConstant: 56),\n            chatButton.heightAnchor.constraint(equalToConstant: 56)\n        ])\n    }\n    \n    @objc private func openChat() {\n        let conversations = CometChatConversations()\n        conversations.set(onItemClick: { [weak self] conversation, _ in\n            let messagesVC = MessagesVC()  // your own VC composing CometChatMessageHeader + List + Composer; see cometchat-ios-components § 12\n            if let user = conversation.conversationWith as? User {\n                messagesVC.set(user: user)\n            } else if let group = conversation.conversationWith as? Group {\n                messagesVC.set(group: group)\n            }\n            conversations.navigationController?.pushViewController(messagesVC, animated: true)\n        })\n        \n        let navController = UINavigationController(rootViewController: conversations)\n        navController.modalPresentationStyle = .pageSheet\n        \n        conversations.navigationItem.leftBarButtonItem = UIBarButtonItem(\n            barButtonSystemItem: .close,\n            target: self,\n            action: #selector(dismissChat)\n        )\n        \n        present(navController, animated: true)\n    }\n    \n    @objc private func dismissChat() {\n        dismiss(animated: true)\n    }\n}\n```\n\n---\n\n## 5. Split View Pattern (iPad)\n\nFor iPad apps with master-detail layout.\n\n### Split View Layout\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  ┌─────────────────────────┐  ┌─────────────────────────────────────────────┐│\n│  │  Conversations          │  │  Messages                                   ││\n│  │  ┌─────────────────────┐│  │  ┌─────────────────────────────────────────┐││\n│  │  │  John Doe           ││  │  │  Header                                 │││\n│  │  │  Jane Smith  ◄──────┼┼──┼──┤─────────────────────────────────────────│││\n│  │  │  Team Chat          ││  │  │  Message List                           │││\n│  │  │                     ││  │  │                                         │││\n│  │  │                     ││  │  │                                         │││\n│  │  │                     ││  │  ├─────────────────────────────────────────┤││\n│  │  │                     ││  │  │  Composer                               │││\n│  │  └─────────────────────┘│  │  └─────────────────────────────────────────┘││\n│  └─────────────────────────┘  └─────────────────────────────────────────────┘│\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### Implementation (UIKit)\n\n```swift\nclass ChatSplitViewController: UISplitViewController {\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        preferredDisplayMode = .oneBesideSecondary\n        preferredSplitBehavior = .tile\n        \n        // Primary: Conversations\n        let conversations = CometChatConversations()\n        conversations.set(onItemClick: { [weak self] conversation, _ in\n            self?.showMessages(for: conversation)\n        })\n        let primaryNav = UINavigationController(rootViewController: conversations)\n        \n        // Secondary: Empty state or messages\n        let emptyVC = EmptyStateViewController()\n        let secondaryNav = UINavigationController(rootViewController: emptyVC)\n        \n        viewControllers = [primaryNav, secondaryNav]\n    }\n    \n    private func showMessages(for conversation: Conversation) {\n        let messagesVC = MessagesVC()  // your own VC composing CometChatMessageHeader + List + Composer; see cometchat-ios-components § 12\n        \n        if let user = conversation.conversationWith as? User {\n            messagesVC.set(user: user)\n        } else if let group = conversation.conversationWith as? Group {\n            messagesVC.set(group: group)\n        }\n        \n        let secondaryNav = UINavigationController(rootViewController: messagesVC)\n        showDetailViewController(secondaryNav, sender: self)\n    }\n}\n\nclass EmptyStateViewController: UIViewController {\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        view.backgroundColor = .systemBackground\n        \n        let label = UILabel()\n        label.text = \"Select a conversation\"\n        label.textColor = .secondaryLabel\n        label.textAlignment = .center\n        \n        view.addSubview(label)\n        label.translatesAutoresizingMaskIntoConstraints = false\n        NSLayoutConstraint.activate([\n            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),\n            label.centerYAnchor.constraint(equalTo: view.centerYAnchor)\n        ])\n    }\n}\n```\n\n---\n\n## 6. Embedded View Pattern\n\nFor embedding chat in a portion of the screen.\n\n### Embedded Layout\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  Your App Header                                            │\n├─────────────────────────────────────────────────────────────┤\n│  ┌─────────────────────────────────────────────────────────┐│\n│  │  Your Content                                           ││\n│  │                                                         ││\n│  └─────────────────────────────────────────────────────────┘│\n├─────────────────────────────────────────────────────────────┤\n│  ┌─────────────────────────────────────────────────────────┐│\n│  │  Embedded Chat (CometChatMessageList + Composer)        ││\n│  │                                                         ││\n│  └─────────────────────────────────────────────────────────┘│\n└─────────────────────────────────────────────────────────────┘\n```\n\n### Implementation (UIKit)\n\n```swift\nclass EmbeddedChatViewController: UIViewController {\n    \n    private var supportUser: User?\n    \n    private lazy var chatContainer: UIView = {\n        let view = UIView()\n        view.backgroundColor = .systemBackground\n        view.layer.cornerRadius = 12\n        view.clipsToBounds = true\n        return view\n    }()\n    \n    private lazy var messageList = CometChatMessageList()\n    private lazy var messageComposer = CometChatMessageComposer()\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        setupUI()\n        fetchSupportUser()\n    }\n    \n    private func setupUI() {\n        view.addSubview(chatContainer)\n        chatContainer.translatesAutoresizingMaskIntoConstraints = false\n        \n        chatContainer.addSubview(messageList)\n        chatContainer.addSubview(messageComposer)\n        \n        messageList.translatesAutoresizingMaskIntoConstraints = false\n        messageComposer.translatesAutoresizingMaskIntoConstraints = false\n        \n        NSLayoutConstraint.activate([\n            // Chat container takes bottom half of screen\n            chatContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),\n            chatContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),\n            chatContainer.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16),\n            chatContainer.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.4),\n            \n            // Message list\n            messageList.topAnchor.constraint(equalTo: chatContainer.topAnchor),\n            messageList.leadingAnchor.constraint(equalTo: chatContainer.leadingAnchor),\n            messageList.trailingAnchor.constraint(equalTo: chatContainer.trailingAnchor),\n            messageList.bottomAnchor.constraint(equalTo: messageComposer.topAnchor),\n            \n            // Composer\n            messageComposer.leadingAnchor.constraint(equalTo: chatContainer.leadingAnchor),\n            messageComposer.trailingAnchor.constraint(equalTo: chatContainer.trailingAnchor),\n            messageComposer.bottomAnchor.constraint(equalTo: chatContainer.bottomAnchor)\n        ])\n    }\n    \n    private func fetchSupportUser() {\n        CometChat.getUser(UID: \"support-agent\") { [weak self] user in\n            guard let user = user else { return }\n            DispatchQueue.main.async {\n                self?.supportUser = user\n                self?.messageList.set(user: user)\n                self?.messageComposer.set(user: user)\n            }\n        } onError: { error in\n            print(\"Error: \\(error?.errorDescription ?? \"\")\")\n        }\n    }\n}\n```\n\n---\n\n## Best Practices\n\n1. **Always wrap in UINavigationController** when presenting CometChat view controllers\n2. **Hide tab bar when pushing messages** using `hidesBottomBarWhenPushed = true`\n3. **Handle keyboard properly** — CometChat components handle this automatically\n4. **Support both orientations** — components adapt to orientation changes\n5. **Test on iPad** — use split view for better iPad experience\n6. **Handle deep links** — navigate to specific conversations from push notifications","tags":["cometchat","ios","placement","skills","agent-skills","ai-agent","chat","claude-code","cursor","messaging","nextjs","react"],"capabilities":["skill","source-cometchat","skill-cometchat-ios-placement","topic-agent-skills","topic-ai-agent","topic-chat","topic-claude-code","topic-cometchat","topic-cursor","topic-messaging","topic-nextjs","topic-react","topic-react-native","topic-ui-kit"],"categories":["cometchat-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cometchat/cometchat-skills/cometchat-ios-placement","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cometchat/cometchat-skills","source_repo":"https://github.com/cometchat/cometchat-skills","install_from":"skills.sh"}},"qualityScore":"0.463","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (26,803 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:04:53.221Z","embedding":null,"createdAt":"2026-05-07T13:05:13.232Z","updatedAt":"2026-05-18T19:04:53.221Z","lastSeenAt":"2026-05-18T19:04:53.221Z","tsv":"'-16':1348,1353 '-20':999,1004 '-5':928 '0':567,582,845,904,945 '0.3':910 '0.4':1358 '1':50,73,590,1422 '10':869 '12':137,504,541,700,863,1039,1190,1295 '16':1343 '2':75,253,598,1432 '20':936,939 '28':898 '3':77,606,615,1442 '4':614,817,906,1451 '5':933,1091,1460 '56':1007,1010 '6':1250,1471 '8':908 '99':948,949 'access':826 'action':720,975,1077 'adapt':1456 'add':711 'addsubview':919 'agent':1390 'alway':1423 'anim':161,518,555,727,743,1062,1082,1089 'app':12,33,60,258,620,632,833,1098,1266 'area':270 'automat':1450 'avail':414 'backgroundcolor':895 'badgelabel':851,920 'badgelabel.heightanchor.constraint':937 'badgelabel.ishidden':943 'badgelabel.text':946 'badgelabel.topanchor.constraint':924 'badgelabel.trailinganchor.constraint':929 'badgelabel.translatesautoresizingmaskintoconstraints':921 'badgelabel.widthanchor.constraint':934 'bar':16,39,255,1435 'barbuttonsystemitem':716,1073 'basic':67 'best':1420 'better':1468 'bind':228 'bodi':200,569,765 'bold':865 'borderedpromin':777 'bottom':1335 'button':713,771,793,819,830,971,981 'button.addtarget':973 'buttonstyl':776 'call':275,411,433,610 'callsnav':426,443 'callsnav.tabbaritem':430 'callsnavigationview':607 'callsvc':423,429 'canimport':420 'case':49 'center':867,1238 'cgrect':879 'cgsize':902 'chang':1459 'chat':260,272,316,329,586,622,636,642,772,823,1115,1256,1271,1332 'chatbutton':968,991 'chatbutton.bottomanchor.constraint':1000 'chatbutton.heightanchor.constraint':1008 'chatbutton.trailinganchor.constraint':995 'chatbutton.translatesautoresizingmaskintoconstraints':992 'chatbutton.widthanchor.constraint':1005 'chatcontain':1287,1320 'chatcontainer.addsubview':1323,1325 'chatcontainer.bottomanchor':1382 'chatcontainer.bottomanchor.constraint':1349 'chatcontainer.heightanchor.constraint':1354 'chatcontainer.leadinganchor':1366,1376 'chatcontainer.leadinganchor.constraint':1339 'chatcontainer.topanchor':1363 'chatcontainer.trailinganchor':1369,1379 'chatcontainer.trailinganchor.constraint':1344 'chatcontainer.translatesautoresizingmaskintoconstraints':1321 'chatnavigationview':187,583 'chatsnav':322,408 'chatsnav.tabbaritem':326 'chatsplitviewcontrol':1123 'chatsvc':319,325 'chatwithsellertap':658 'class':285,650,838,962,1122,1219,1277 'close':712,717,794,1074 'coder':886,889,890 'cometchat':2,8,28,134,501,538,697,1036,1187,1429,1446 'cometchat-ios-compon':133,500,537,696,1035,1186 'cometchat-ios-plac':1 'cometchat.getuser':671,800,1386 'cometchatcalllog':424 'cometchatcallssdk':416,421 'cometchatconvers':71,115,236,239,250,450,453,1017,1137 'cometchatgroup':374 'cometchatmessagecompos':82,1309 'cometchatmessagehead':80,129,496,533,692,1031,1182 'cometchatmessagelist':81,1272,1304 'cometchatsdk':185,284 'cometchatuikitswift':183,282 'cometchatus':342 'common':56 'compon':29,136,503,540,699,1038,1189,1447,1455 'compos':128,131,495,498,532,535,646,691,694,1030,1033,1118,1181,1184,1273,1373 'connectionopt':95 'constant':927,932,998,1003,1342,1347,1352 'contain':1333 'content':269,300,633,834,1269 'context':234,235,251,252 'control':166,961,1431 'convers':62,72,74,76,111,114,119,120,157,171,193,212,215,216,231,238,241,244,246,452,458,482,1016,1022,1068,1107,1134,1136,1142,1147,1152,1173,1174,1234,1478 'conversation.conversationwith':141,151,463,474,1043,1053,1194,1204 'conversations.navigationcontroller':1059 'conversations.navigationitem.leftbarbuttonitem':1071 'conversations.onitemclick':240 'conversations.set':116,454,1018,1138 'conversationslistview':204,226 'count':953,956 'cover':35 'creat':110 'createchatstab':320,449 'deep':1473 'detail':635,770,1102 'didset':846 'differ':47 'dismiss':742,1088 'dismisschat':723,741,1079,1087 'dispatchqueue.main.async':684,805,1401 'doe':1110 'els':103,147,470,665,682,1049,1200,1399 'embed':19,44,1251,1255,1263,1270 'embeddedchatviewcontrol':1278 'empti':1154 'emptystateviewcontrol':1160,1220 'emptyvc':1159,1165 'endif':444 'equalto':925,930,996,1001,1245,1248,1340,1345,1350,1355,1362,1365,1368,1371,1375,1378,1381 'equaltoconst':938,1006,1009 'error':730,733,736,811,814,815,1414,1417,1418 'errordescript':737,816,1419 'exist':299 'experi':1470 'fals':198,758,796,922,993,1242,1322,1328,1330 'featur':266,626 'fetch':667,734 'fetchsellerandshowchat':775,799 'fetchsupportus':1315,1385 'float':818,829 'floatingchatbutton':839,969,972 'flow':69 'frame':878,881,882 'func':87,232,247,289,294,448,484,521,657,740,798,893,941,951,983,988,1013,1086,1126,1170,1223,1311,1317,1384 'greaterthanorequaltoconst':935 'group':150,153,155,156,274,370,379,384,393,473,476,480,524,525,543,544,602,1052,1055,1057,1058,1203,1206,1208,1209 'groupsnav':386,410 'groupsnav.tabbaritem':390 'groupsnavigationview':599 'groupsvc':373,389 'groupsvc.set':375 'guard':97,661,678,1395 'half':1336 'handl':1443,1448,1472 'header':1111,1267 'height':905 'hide':1433 'hidesbottombarwhenpush':1440 'home':271,296,307,578 'homevc':302,407 'homevc.tabbaritem':304 'homeview':575 'homeviewcontrol':303 'hous':311,580 'house.fill':315 'ibact':656 'imag':308,330,362,394,434 'implement':83,177,276,557,647,745,835,1119,1274 'import':180,182,184,279,281,283 'init':877,885 'instal':418 'int':844,954 'integr':40 'io':3,11,32,135,502,539,698,1037,1188 'ipad':1095,1097,1463,1469 'ispres':208,779 'jane':1112 'john':644,1109 'keyboard':1444 'label':577,585,593,601,609,854,875,1229,1240 'label.backgroundcolor':856 'label.centerxanchor.constraint':1244 'label.centeryanchor.constraint':1247 'label.clipstobounds':870 'label.font':860 'label.ishidden':872 'label.layer.cornerradius':868 'label.text':1231 'label.textalignment':866,1237 'label.textcolor':858,1235 'label.translatesautoresizingmaskintoconstraints':1241 'layer.cornerradius':897 'layer.shadowcolor':899 'layer.shadowoffset':901 'layer.shadowopacity':909 'layer.shadowradius':907 'layout':268,630,831,1103,1106,1264 'lazi':849,966,1285,1301,1306 'let':98,105,113,122,139,149,167,211,237,301,318,321,340,353,372,385,422,425,451,461,472,489,511,526,548,662,679,685,704,751,782,853,970,1015,1024,1041,1051,1064,1135,1148,1158,1161,1175,1192,1202,1210,1228,1289,1396 'link':1474 'list':112,130,497,534,693,1032,1117,1183,1360 'main':265 'maintabbarcontrol':286 'maintabview':561 'mainviewcontrol':963 'makeuiviewcontrol':233 'master':1101 'master-detail':1100 'messag':59,333,588,645,828,1108,1116,1157,1359,1438 'message.fill':337,914 'messagecompos':1308,1326 'messagecomposer.bottomanchor.constraint':1380 'messagecomposer.leadinganchor.constraint':1374 'messagecomposer.set':1410 'messagecomposer.topanchor':1372 'messagecomposer.trailinganchor.constraint':1377 'messagecomposer.translatesautoresizingmaskintoconstraints':1329 'messagelist':1303,1324 'messagelist.bottomanchor.constraint':1370 'messagelist.leadinganchor.constraint':1364 'messagelist.set':1406 'messagelist.topanchor.constraint':1361 'messagelist.trailinganchor.constraint':1367 'messagelist.translatesautoresizingmaskintoconstraints':1327 'messagesvc':123,124,160,490,491,517,527,528,554,686,687,708,1025,1026,1061,1176,1177,1214 'messagesvc.hidesbottombarwhenpushed':508,545 'messagesvc.navigationitem.leftbarbuttonitem':714 'messagesvc.set':144,154,505,542,701,1046,1056,1197,1207 'messagesview':214,786 'messagesviewcontrol':78 'modal':17,41,616,628,629,639 'multipli':1357 'navcontrol':168,173,512,549,705,726,1065,1081 'navcontroller.modalpresentationstyle':709,1069 'navcontroller.pushviewcontroller':516,553 'navig':13,36,51,65,68,165,1475 'navigationbarlead':792 'navigationcontrol':158 'navigationdestin':207 'navigationstack':203,785 'newvalu':220,223 'nil':224 'normal':916 'notif':1481 'nscoder':887 'nslayoutconstraint.activate':923,994,1243,1331 'objc':738,1011,1084 'ofsiz':862 'onchang':217 'one':262 'onebesidesecondari':1130 'onerror':729,810,1413 'onitemclick':117,344,376,455,1019,1139 'onto':63 'openchat':977,1014 'openmessag':350,382,467,478,485,522 'option':94 'orient':1454,1458 'overrid':288,876,982,1125,1222,1310 'pagesheet':710,1070 'pattern':14,37,53,57,256,618,820,1094,1253 'person.2':365,596 'person.2.fill':369 'person.3':397,604 'person.3.fill':401 'phone':437,612 'phone.fill':441 'place':27 'placement':4,791 'portion':1259 'practic':1421 'preferreddisplaymod':1129 'preferredsplitbehavior':1131 'present':42,617,627,640,725,1080,1428 'primari':1133 'primarynav':1149,1167 'print':732,813,1416 'privat':190,195,293,447,483,520,564,739,755,760,797,841,848,892,940,965,987,1012,1085,1169,1280,1284,1300,1305,1316,1383 'product':634,769 'productdetailview':749 'productdetailviewcontrol':651 'proper':1445 'purpos':21 'push':61,79,1437,1480 'pushviewcontrol':159,1060 'put':7 'quick':825 'requir':884 'return':104,245,481,666,683,874,980,1298,1400 'rootviewcontrol':170,324,356,388,406,428,707,1067,1151,1164,1213 'scene':88,89,100 'scenedelegate.swift':86 'screen':1262,1338 'secondari':625,1153 'secondarylabel':1236 'secondarynav':1162,1168,1211,1216 'see':132,499,536,695,1034,1185 'select':573,1232 'selectedconvers':192,205,206,213,219,230,243 'selectedimag':312,334,366,398,438 'selectedtab':566,574 'selectedviewcontrol':513,550 'selector':721,976,1078 'self':346,349,378,381,457,466,477,675,719,722,724,974,1021,1076,1141,1144,1218,1392,1402,1405,1409 'self.seller':806 'self.showchat':808 'self.window':174 'seller':638,669,762,774,783,784,788 'selleruid':654,663,664,673,752,802 'sender':659,1217 'session':92 'setimag':911 'setunreadcount':952 'setupbutton':883,891,894 'setupfloatingbutton':986,989 'setuptab':292,295 'setupui':1314,1318 'sever':264 'sheet':778 'showchat':757,780,795 'showdetailviewcontrol':1215 'showmessag':197,209,222,1145,1171 'skill':23 'skill-cometchat-ios-placement' 'smith':1113 'source-cometchat' 'specif':1477 'split':1092,1104,1465 'stack':52,66 'state':189,194,563,754,759,1155 'string':655,753 'struct':186,225,560,748 'super.init':880,888 'super.viewdidload':291,985,1128,1225,1313 'support':822,1389,1452 'support-ag':1388 'supportus':1282,1403 'swift':85,179,278,559,649,747,837,1121,1276 'swiftui':178,181,558,746 'systembackground':1227,1293 'systemblu':896 'systemfont':861 'systemimag':579,587,595,603,611 'systemnam':310,314,332,336,364,368,396,400,436,440,913 'systemr':857 'tab':15,38,254,267,297,317,339,371,403,412,446,1434 'tabitem':576,584,592,600,608 'tabs.append':442 'tabview':572 'tag':581,589,597,605,613 'take':1334 'target':718,1075 'teach':24 'team':1114 'test':1461 'tile':1132 'tintcolor':917 'titl':306,328,360,392,432 'toolbar':789 'toolbaritem':790 'topanchor':926 'topic-agent-skills' 'topic-ai-agent' 'topic-chat' 'topic-claude-code' 'topic-cometchat' 'topic-cursor' 'topic-messaging' 'topic-nextjs' 'topic-react' 'topic-react-native' 'topic-ui-kit' 'touchupinsid':979 'trailinganchor':931 'true':162,509,519,546,556,728,744,809,871,873,1063,1083,1090,1297,1441 'uibarbuttonitem':715,1072 'uibutton':660,840 'uicolor.black.cgcolor':900 'uid':672,801,1387 'uiimag':309,313,331,335,363,367,395,399,435,439,912 'uikit':84,277,280,648,836,1120,1275 'uilabel':852,855,1230 'uinavigationcontrol':70,169,323,355,387,405,427,515,552,706,1066,1150,1163,1212,1426 'uiscen':90 'uiscene.connectionoptions':96 'uiscenesess':93 'uisplitviewcontrol':1124 'uitabbarcontrol':287 'uitabbaritem':305,327,359,391,431 'uiview':1288,1291 'uiviewcontrol':249,404,652,964,1221,1279 'uiviewcontrollerrepresent':227 'uiwindow':107 'uiwindowscen':102 'unreadcount':843,944,947,950,955 'updatebadg':847,942 'updateuiviewcontrol':248 'usag':957 'use':48,1439,1464 'user':140,143,145,146,273,338,347,352,361,462,465,469,487,488,506,507,594,670,676,680,681,702,703,735,763,787,803,807,1042,1045,1047,1048,1193,1196,1198,1199,1283,1393,1397,1398,1404,1407,1408,1411,1412 'usersnav':354,409 'usersnav.tabbaritem':358 'usersnavigationview':591 'usersvc':341,357 'usersvc.set':343 'var':191,196,199,229,402,565,568,653,756,761,764,842,850,967,1281,1286,1302,1307 'vc':127,494,531,690,1029,1180 'view':20,45,188,202,562,571,750,767,960,1093,1105,1252,1290,1299,1430,1466 'view.addsubview':990,1239,1319 'view.backgroundcolor':1226,1292 'view.centerxanchor':1246 'view.centeryanchor':1249 'view.clipstobounds':1296 'view.heightanchor':1356 'view.layer.cornerradius':1294 'view.leadinganchor':1341 'view.safearealayoutguide.bottomanchor':1002,1351 'view.safearealayoutguide.trailinganchor':997 'view.trailinganchor':1346 'viewcontrol':445,1166 'viewdidload':290,984,1127,1224,1312 'vstack':768 'weak':118,345,377,456,674,1020,1140,1391 'weight':864 'white':859,918 'width':903 'willconnectto':91 'window':106,175 'window.makekeyandvisible':176 'window.rootviewcontroller':172 'windowscen':99,108,109 'wrap':163,1424 'x':641","prices":[{"id":"b9a9fa84-60db-4b7a-9280-d9559154f01f","listingId":"082cd0d6-b17f-4a68-a8b5-628884ea9ccd","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cometchat","category":"cometchat-skills","install_from":"skills.sh"},"createdAt":"2026-05-07T13:05:13.232Z"}],"sources":[{"listingId":"082cd0d6-b17f-4a68-a8b5-628884ea9ccd","source":"github","sourceId":"cometchat/cometchat-skills/cometchat-ios-placement","sourceUrl":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-ios-placement","isPrimary":false,"firstSeenAt":"2026-05-07T13:05:13.232Z","lastSeenAt":"2026-05-18T19:04:53.221Z"}],"details":{"listingId":"082cd0d6-b17f-4a68-a8b5-628884ea9ccd","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cometchat","slug":"cometchat-ios-placement","github":{"repo":"cometchat/cometchat-skills","stars":27,"topics":["agent-skills","ai-agent","chat","claude-code","cometchat","cursor","messaging","nextjs","react","react-native","ui-kit"],"license":null,"html_url":"https://github.com/cometchat/cometchat-skills","pushed_at":"2026-05-18T05:04:24Z","description":"Add CometChat chat to any React, Next.js, React Native, Angular, Android, iOS, or Flutter project through your AI coding agent. Works with Claude Code, Cursor, Codex, VS Code Copilot, Windsurf, Cline, Kiro, and 50+ more agents.","skill_md_sha":"5ed59990dfd8302acd10437cb7a203479cfb0c26","skill_md_path":"skills/cometchat-ios-placement/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-ios-placement"},"layout":"multi","source":"github","category":"cometchat-skills","frontmatter":{"name":"cometchat-ios-placement","license":"MIT","description":"WHERE to put CometChat in your iOS app — navigation patterns, tab bars, modals, and embedded views.","compatibility":"CometChatUIKitSwift ^5; iOS 13+"},"skills_sh_url":"https://skills.sh/cometchat/cometchat-skills/cometchat-ios-placement"},"updatedAt":"2026-05-18T19:04:53.221Z"}}