Metadata

Metadata provides an elegant mechanism for expressing and synchronizing contextual information about conversations. This is implemented as a free-form structure of string key-value pairs that is automatically synchronized among the participants in a conversation. Example use cases of metadata include:

  • Setting a conversation title.
  • Attaching dates or tags to the conversation.
  • Storing a reference to a background image URL for the conversation.

The following demonstrates setting metadata on a conversation:

NSDictionary *metadata = @{@"title" : @"My Conversation",
                           @"theme" : @{
                                @"background_color" : @"333333",
                                @"text_color" : @"F8F8EC",
                                @"link_color" : @"21AAE1"},
                           @"created_at" : @"Dec, 01, 2014",
                           @"img_url" : @"/path/to/img/url"};
[self.conversation setValuesForMetadataKeyPathsWithDictionary:metadata merge:YES];

For convenience and to facilitate the namespacing of information within metadata, values may be manipulated as key paths. A key path is a dot (.) delimited string that identifies a series of nested keys leading to a leaf value. For example, given the above metadata structure, an application could change the name of a participant via the following:

[conversation setValue:@"FFFFFF" forMetadataAtKeyPath:@"theme.background_color"];

You can also initialize a new conversation with metadata by passing in LYRConversationOptionsMetadataKey option.

LYRConversation *conversation = [layerClient newConversationWithParticipants:[NSSet setWithObjects:@"USER-IDENTIFIER", nil] options:options:@{LYRConversationOptionsMetadataKey : metadata } error:&error];

Applications can fetch metadata for a given conversation by accessing the public metadata property on LYRConversation objects.

NSString *title = [conversation.metadata valueForKey:@"title"];

Applications can also fetch metadata using a keypath. For the example, given the above metadata structure, this code will return the value of “333333”:

NSString *color = [conversation.metadata valueForKeyPath:@"theme.background_color"];

Using metadata

@interface LYRConversation (Metadata)

/**
 @abstract Returns the metadata associated with the Conversation.
 */
@property (nonatomic, readonly) NSDictionary *metadata;

/**
 @abstract Sets the value for a particular metadata key path to the given value.
 @param value The value to assign to the keypath.
 @param keyPath A key-path to the metadata to be assigned a new value.
 */
- (void)setValue:(NSString *)value forMetadataAtKeyPath:(NSString *)keyPath;

/**
 @abstract Replaces or merges the current metadata with a new dictionary of values.
 @param metadata The metadata to be assigned or merged.
 @param merge A Boolean value that determines if the given value should be assigned or merged.
 */
- (void)setValuesForMetadataKeyPathsWithDictionary:(NSDictionary *)metadata merge:(BOOL)merge;

/**
 @abstract Deletes existing value for the specified key-path from the metadata.
 @param keyPath The key-path to the metadata to be deleted.
 */
- (void)deleteValueForMetadataAtKeyPath:(NSString *)keyPath;
@end

You can also create a new conversation with metadata by passing in a LYRConversationOptions object with a specified metadata value:

LYRConversationOptions *conversationOptions = [LYRConversationOptions new];
conversationOptions.metadata = metadata;
LYRConversation *conversation = [layerClient newConversationWithParticipants:[NSSet setWithObjects:@"USER_ID", nil] options:conversationOptions error:&error];

Warning

While this feature is both powerful and convenient, it is not designed to serve as a general purpose data store. It’s important to understand the intended use cases and limitations associated with the feature to ensure an ideal user experience. In particular, keep in mind that:

  • Metadata is implemented with “last writer wins” semantics on a per key basis. This means that multiple mutations by independent users to a given key will result in a single stored value. No locking or other coordination is performed across participants.
  • Metadata is automatically synchronized by each participant in the conversation. While Layer has gone to great lengths to implement metadata in a way that maximizes efficiency on the wire, it is important that the amount of data stored in metadata is kept to a minimum to ensure the quickest synchronization possible.
  • Metadata values must be represented as strings. To ensure a satisfying user experience developers are strongly discouraged from storing any sort of binary data representation (including thumbnail images) via metadata. Instead, consider storing a URL or other reference to data that is transmitted out of band from synchronization.
  • Metadata is limited to the storage of a maximum of 2KB of data under each key. Keys must be alphanumeric and may include hyphens and underscores, but cannot contain spaces. If your metadata key contains space you may run into issues if you try to query them. Nested structures may be used to facilitate efficient namespacing of content.
  • There is not currently any limit enforced on the number of keys stored into the metadata structure. Because mutations are performed on a per key basis, it is advantageous to structure your data in such a way that smaller amounts of data are stored under a larger number of keys. Note that we may introduce a key limit in future versions.
  • Mutable Conversation metadata should only be used to store information associated with the Conversation itself – not individual messages. As the number of metadata keys grow synchronization will take longer to complete. Because Conversations can be very long lived, performance can be severely impacted if dynamically computed keys (such as those built from message identifiers) are utilized.
Typing indicators Synchronization