jessesquires / JSQMessagesViewController

An elegant messages UI library for iOS
https://www.jessesquires.com/blog/officially-deprecating-jsqmessagesviewcontroller/
Other
11.14k stars 2.82k forks source link

iOS 9 Scrolling collectionView not smooth #1264

Closed vazin closed 9 years ago

vazin commented 9 years ago

This problem appeared in ios 9. Even in the demo example. Also in other apps i can see such problems with UITableViews and UICollectionViews. In ios 8 everything works fine. Do you have any suggestions about it?

dpreston10 commented 9 years ago

I also notice that the building of the collection view seems to be much slower than in iOS 8

aspcartman commented 9 years ago

Profiler says that bubble images are getting reloaded from png on each display call. Over and over again.

screen shot 2015-10-26 at 06 49 03
aspcartman commented 9 years ago

Actually I was wrong about bubble cells. In my case it was my user's avatars. Forced them to cached prerendered versions and everything is smooth again.

vazin commented 9 years ago

@aspcartman Thank you for taking part in a question. Can you provide some code example? As i understand prerendered avatars are stored in dictionary and loaded only once. Also I disabled avatars but some lags have remained.

aspcartman commented 9 years ago

@vazin np :)

Bubbles:

// No prerendering: images are stretchable and it doesn't worth it. Just acquire the JSQImage pair and save it in ivar
JSQMessagesBubbleImageFactory *factory  = [JSQMessagesBubbleImageFactory new];
_incomingImage = [factory incomingMessagesBubbleImageWithColor:[UIColor xs_darkBlueColor]];
_outgoingImage = [factory outgoingMessagesBubbleImageWithColor:[UIColor xs_blueColor]];

Avatars:

// Avatar is stored inside the User object, prerendered by custom lazy getter
- (UIImage *) avatar
{
    if (!_preRenderedAvatar)
    {
        _preRenderedAvatar = [[UIImage imageWithData:self.photoData] preRender];
    }
    return _preRenderedAvatar;
}

prerender:

- (UIImage *) imageSized:(CGSize)size
{
    CGRect     newRect  = CGRectIntegral(CGRectMake(0, 0, size.width, size.height));
    CGImageRef imageRef = self.CGImage;

    UIGraphicsBeginImageContextWithOptions(size, NO, 1);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);

    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, size.height);
    CGContextConcatCTM(context, flipVertical);

    CGContextDrawImage(context, newRect, imageRef);

    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage    *newImage   = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();
    return newImage;
}

- (UIImage *) preRender
{
    return [self imageSized:self.size];
}

That's it. Now everything is smooth and nice :) Good luck!

jessesquires commented 9 years ago

Thanks @aspcartman ! :smile:

To clarify: the library does not cache avatar/bubble image data. This is left up to the client.