Rich Content

If a Message Part contains a large amount of content (> 2KB), it will be sent as rich content instead. This has no effect on how you send a Message.

Sending Rich Content

Sending large messages works the same way as standard messages:

// Creates a message part with an image and sends it to the specified conversation
NSData *imageData = UIImagePNGRepresentation(image);
LYRMessagePart *messagePart = [LYRMessagePart messagePartWithMIMEType:@"image/png" data:imageData];
LYRMessage *message = [layerClient newMessageWithParts:@[messagePart] options:nil error:nil];

// Sends the specified message
NSError *error = nil;
BOOL success = [conversation sendMessage:message error:&error];
if (success) {
  NSLog(@"Message enqueued for delivery");
} else {
  NSLog(@"Message send failed with error: %@", error);
}

Receiving Rich Content

There are some differences in how such a Message would be received:

Once the rich content has been downloaded (whether automatically or manually with the downloadContent method), it can be filtered by its MIME type and handled appropriately.

// Filter for PNG message part
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"MIMEType == %@", @"image/png"];
LYRMessagePart *messagePart = [[message.parts filteredArrayUsingPredicate:predicate] firstObject];

// If it's ready, render the image from the message part
if (!(messagePart.transferStatus == LYRContentTransferReadyForDownload || 
      messagePart.transferStatus == LYRContentTransferDownloading)) {
  self.imageView.image = [UIImage imageWithData:messagePart.data];
}

Monitoring transfer progress

As Rich Content may involve upload of large files, being able to monitor the progress of sending these Messages can be significant. You can access the progress of any message part upload (while sending) or download (while receiving) via its progress.

LYRMessagePart *messagePart = message.parts.firstObject;

// Auto-download
LYRProgress *progress1 = messagePart.progress;

// Manual download
NSError *error;
LYRProgress *progress2 = [messagePart downloadContent:&error];

The progress property on the message part will reflect upload progress when sending a message.

The fractionCompleted property of LYRProgress reflects the download/upload progress as a percent value (ranging from 0.0 to 1.0). The LYRProgress object also declares the LYRProgressDelegate protocol, which you can implement to be notified of progress changes.

@interface MyAwesomeApp () <LYRProgressDelegate>

@end

@implementation MyAwesomeApp

- (void)progressDidChange:(LYRProgress *)progress
{
    NSLog(@"Transfer progress changed %@", progress.fractionCompleted);
}

Best practice

The LYRProgress doesn’t contain a reference back to the message part that it’s associated with. A common UI is to show a progress bar in the view that will load the contents of the message part once it’s downloaded. If you are doing this, set the progress delegate to the content view itself, and update the progress bar when the progress delegate method is called.

Aggregate progress

You can get the progress of multiple operations in one progress object by combining LYRProgress objects into a LYRAggregateProgress object (a subclass of LYRProgress). As each individual LYRProgress object updates, the aggregate progress will update accordingly based on the total size of all the operations.

LYRMessagePart *part1 = self.message.parts[0];
LYRMessagePart *part2 = self.message.parts[1];
LYRMessagePart *part3 = self.message.parts[2];

NSError *error;
LYRProgress *progress1 = [LYRClient downloadContent:part1 error:&error];
LYRProgress *progress2 = [LYRClient downloadContent:part2 error:&error];
LYRProgress *progress3 = [LYRClient downloadContent:part3 error:&error];

LYRAggregateProgress *aggregateProgress = [LYRAggregateProgress aggregateProgressWithProgresses:@[progress1, progress2, progress3]];

Transfer status

LYRMessagePart objects provide a transferStatus property, which can be one of five values:

  • LYRContentTransferAwaitingUpload: The content has been saved in the local queue but hasn’t had a chance to start uploading yet
  • LYRContentTransferUploading: Content is currently uploading
  • LYRContentTransferReadyForDownload: Content is fully uploaded and ready on Layer servers but hasn’t had a chance to start downloading to the device yet
  • LYRContentTransferDownloading: Content is currently downloading
  • LYRContentTransferComplete: Content has finished uploading or downloading

The transferStatus value is useful for certain use cases, such as only showing fully-downloaded messages. It is queryable.

Background transfers

You can continue a download or upload while the app is in the background by enabling background transfers.

layerClient.backgroundContentTransferEnabled = YES;

If you enable background content transfer, your app delegate must implement this method and call handleBackgroundContentTransfersForSession:completion: on the Layer client:

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
{
    // You'll have to get access to your `layerClient` instance
    // This may be a property in your app delegate
    // Or accesible via a `LayerController` or similar class in your app
    [layerClient handleBackgroundContentTransfersForSession:identifier completion:^(NSArray *changes, NSError *error)completionHandler {
        NSLog(@"Background transfers finished with %lu change(s)", (unsigned long)changes.count);
        completionHandler();
    }];
}
Announcements Querying