Key Benefit: Maintain accurate unread counts and provide clear user feedback by intelligently marking messages as read when users interact with them, ensuring precise conversation state management.

Feature Overview

Message Read Status enables precise tracking of individual message reading states, allowing you to mark messages as read when users view them and maintain accurate unread counts across your chat application. This feature provides the foundation for reliable conversation state management and user engagement tracking.

Individual Message Tracking

Granular read state management
  • Mark specific messages as read
  • Real-time status updates

Unread Count Accuracy

Precise count management
  • Immediate count updates
  • Consistent state synchronization

Implementation Guide

Mark messages as read when users view themImplement fundamental read tracking to update message status and maintain accurate unread counts as users interact with conversations.

Core Read Operations

OperationPurposeWhen to Use
markRead()Mark a specific message as readUser views message content
Automatic DetectionMark messages read on viewMessage appears in viewport
Latest Message ReadMark newest message readChat screen opens

Code Examples

// Basic message read marking
func markMessageAsRead(message: AmityMessage) {
    message.markRead()
    print("Message \(message.messageId) marked as read")
}

// Mark messages as read in table view
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    guard let message = getMessage(for: indexPath) else { return }
    
    // Mark message as read when it appears on screen
    message.markRead()
}

// Mark latest message as read when entering chat
class ChatViewController: UIViewController {
    private var messageRepository: AmityMessageRepository!
    private var token: AmityNotificationToken?
    private var isFirstLoad = true
    
    override func viewDidLoad() {
        super.viewDidLoad()
        observeMessages()
    }
    
    private func observeMessages() {
        let messageQuery = AmityMessageQueryOptions(
            subChannelId: subChannelId,
            sortOption: .lastCreated
        )
        
        token = messageRepository.getMessages(options: messageQuery).observe { liveCollection, _, error in
            guard error == nil else { return }
            
            // Mark latest message as read on first load
            if self.isFirstLoad, let latestMessage = liveCollection.object(at: 0) {
                latestMessage.markRead()
                self.isFirstLoad = false
            }
            
            // Update UI with messages
            self.updateMessagesList(liveCollection)
        }
    }
    
    private func updateMessagesList(_ collection: AmityCollection<AmityMessage>) {
        // Update table view with new messages
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
}

// Smart read tracking with visibility detection
func configureMessageCell(_ cell: MessageTableViewCell, with message: AmityMessage, at indexPath: IndexPath) {
    cell.configure(with: message)
    
    // Mark as read when cell becomes fully visible
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        if self.tableView.indexPathsForVisibleRows?.contains(indexPath) == true {
            message.markRead()
        }
    }
}
Timing Considerations: Mark messages as read when they become visible to users, not just when they’re loaded. This provides more accurate engagement tracking and better user experience.

Read Tracking Strategies

Best Practices

Implementation Strategy: Start with basic manual read tracking (mark on tap), then add visibility-based automatic detection. Focus on user control and clear feedback to build trust in your read tracking system.