Browse SDKs · iOS
Platform
SDKsiOS

Receive messages

Register the iOS message listener and merge new messages into conversation state.

Copy

The iOS SDK delivers regular new messages, online-only messages, revocations, deletions, and read receipts through OIMAdvancedMsgListener. Register the listener once when initializing the message state layer and retain the listener strongly because OIMCallbacker holds only a weak reference.

Message types

Each regular event returns one OIMMessageInfo. Choose text, @ text, custom, image, audio, video, file, or fallback rendering according to the message element. Do not assume that every message contains textElem. For media messages, read the remote URL, size, name, duration, and snapshot from the element; do not upload the resource again.

A message may belong to a conversation that is not currently open. Determine the target conversation first from sessionType, sendID, recvID, and groupID, then merge idempotently by clientMsgID.

Common OIMMessageInfo properties used for reception, routing, and merging are:

PropertyTypeDescription
clientMsgIDNSString * _NullableClient message ID; use it as the stable unique merge key when non-empty.
serverMsgIDNSString * _NullableServer message ID. It does not replace clientMsgID for local merging.
sessionTypeOIMConversationTypeConversation type enum used to determine single or group chat routing.
sendIDNSString * _NullableSender user ID.
recvIDNSString * _NullableRecipient user ID.
groupIDNSString * _NullableTarget group ID for group messages.
contentTypeOIMMessageContentTypeContent type enum determining which content element to render.
sendTimeNSTimeIntervalMessage dispatch timestamp used for sorting; cannot serve as a unique ID.
statusOIMMessageStatusMessage delivery status enum.
isReadBOOLRead receipt state recorded by the SDK.

Content properties such as textElem, pictureElem, soundElem, videoElem, fileElem, atTextElem, and customElem may be nil. Check both contentType and the corresponding element when rendering. Display fallback placeholders when expected content is missing instead of force-unwrapping.

Register the new-message listener

@interface MessageStore () <OIMAdvancedMsgListener>
@end

@implementation MessageStore

- (void)startListening {
    [[OIMManager callbacker] addAdvancedMsgListener:self];
}

- (void)stopListening {
    [[OIMManager callbacker] removeAdvancedMsgListener:self];
}

- (void)onRecvNewMessage:(OIMMessageInfo * _Nullable)message {
    if (message.clientMsgID.length == 0) {
        return;
    }
    [self mergeMessage:message];
}

- (void)onRecvOnlineOnlyMessage:(OIMMessageInfo * _Nullable)message {
    if (message.clientMsgID.length == 0) {
        return;
    }
    [self handleOnlineOnlyMessage:message];
}

@end

Register the global message listener after initSDK succeeds and before login. Remove the listener with the same instance when signing out, switching accounts, or destroying the state layer. The callback message parameter can be nil, so validate clientMsgID before processing. Each callback delivers a single OIMMessageInfo model.

Online-only messages are not stored in regular offline history and are suitable for transient hints or business notifications. For sending parameters, see Send a message.

Merge messages

Resolve the target conversation from routing fields first, then merge idempotently by clientMsgID. A new-message event can overlap with a send-success callback or history query result, so never append it directly without deduplication.

History queries establish the baseline snapshot, onRecvNewMessage: provides online increments, and the SDK synchronizes offline changes upon logging in. After synchronization completes, re-query the current conversation's history to reconcile list state.

Retrieve history when first opening a conversation

Event callbacks only supply newly arriving messages. Use getAdvancedHistoryMessageList:onSuccess:onFailure: to retrieve history when opening a conversation, scrolling upward, or refreshing a list after synchronization. Set startClientMsgID to nil for the first page and use the boundary message's clientMsgID for subsequent pages. See Load message history for details.

The query callback returns a snapshot of messages and does not trigger the new-message listener. Both pagination and incoming events must use identical conversation routing and clientMsgID deduplication rules.

Mark the conversation as read

After the user opens the conversation and views visible messages, invoke the mark-as-read API to clear the unread counter. For one-to-one chat receipts, see Mark a conversation as read. For member-level group receipts, see Report group-message read status.

Other message events

Query APIs, local insertion, and message creation do not trigger onRecvNewMessage:.

Verify the receiving flow

  • Send a message to the target one-to-one or group chat from another account and verify that it merges exactly once by conversation and clientMsgID.
  • Send an online-only message and verify that it arrives through onRecvOnlineOnlyMessage: and is not returned by history queries.
  • Revoke or delete a message and verify that the message view updates the corresponding bubble by clientMsgID.
  • After signing out or switching accounts, verify that the listener was removed and does not process duplicate messages after the next login.