3

i am developing chat application , in which i need to display text , images , video which i am getting from json. to display image data there is a method in JSQ framework:

 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:entity.image.imageUrl]];
 UIImage *imageFromUrl = [UIImage imageWithData:data];
JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] initWithImage:imageFromUrl];
JSQMessage *photoMessage = [[JSQMessage alloc] initWithSenderId:senderId senderDisplayName:displayName date:entity.messageDate media:photoItem];

but this will take long time to load as i have to display large number of images. so how to display image from url in chat async?

sulabh
  • 249
  • 5
  • 22

2 Answers2

11

This is how I did:

#import "JSQPhotoMediaItem.h"

@interface ChatAsyncPhoto : JSQPhotoMediaItem

@property (nonatomic, strong) UIImageView *asyncImageView;

- (instancetype)initWithURL:(NSURL *)URL;

@end

#import "ChatAsyncPhoto.h"
#import "UIColor+JSQMessages.h"
#import "JSQMessagesMediaPlaceholderView.h"
#import "UIImageView+WebCache.h"

@implementation ChatAsyncPhoto

- (instancetype)init
{
    return [self initWithMaskAsOutgoing:YES];
}

- (instancetype)initWithURL:(NSURL *)URL {
    self = [super init];
    if (self) {
        CGSize size = [self mediaViewDisplaySize];

        self.asyncImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
        self.asyncImageView.contentMode = UIViewContentModeScaleToFill;
        self.asyncImageView.clipsToBounds = YES;
        self.asyncImageView.layer.cornerRadius = 20;
        self.asyncImageView.backgroundColor = [UIColor jsq_messageBubbleLightGrayColor];

        UIView *activityIndicator = [JSQMessagesMediaPlaceholderView viewWithActivityIndicator];
        activityIndicator.frame = self.asyncImageView.frame;

        [self.asyncImageView addSubview:activityIndicator];

        UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:URL.absoluteString];
        if(image == nil)
        {
            [self.asyncImageView sd_setImageWithURL:URL completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                if (error == nil) {
                    [self.asyncImageView setImage:image];
                    [activityIndicator removeFromSuperview];
                } else {
                    NSLog(@"Image downloading error: %@", [error localizedDescription]);
                }
            }];
        } else {
            [self.asyncImageView setImage:image];
            [activityIndicator removeFromSuperview];
        }
    }

    return self;
}

#pragma mark - JSQMessageMediaData protocol
- (UIView *)mediaView
{
    return self.asyncImageView;
}

#pragma mark - NSCoding
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    NSLog(@"init coder has not been implemented");

    return self;
}

@end

Then you can use the class as follows:

ChatAsyncPhoto *photoItem = [[ChatAsyncPhoto alloc] initWithURL:[NSURL URLWithString:messageItem.content]];
JSQMessage *message = [[JSQMessage alloc] initWithSenderId:messageItem.userInfo.id
                                         senderDisplayName:messageItem.userInfo.username
                                                      date:[DateUtil getTimeDateStringFromDate:messageItem.createdDate]
                                                     media:photoItem];
[self.chatData.messages addObject:message];
-1

I would take a look into

self.sd_setImageWithURL(NSURL!, forState: UIControlState, placeholderImage: UIImage!, options: SDWebImageOptions)

and in this case self would be your image view. There are a couple of different methods with different options. This is an async call so it will not block you UI and if you use .RefreshCached as your options: it will update when the call returns.

Dan Leonard
  • 3,325
  • 1
  • 20
  • 32