Lag UICollection View Scroll com SDWebImage

fundo

Eu procurei em torno de SO e fórum da Apple. Muitas pessoas falaram sobre o desempenho da célula de exibição de coleção com a imagem. A maioria deles disse que está atrasada desde que carregou a imagem no tópico principal.

UsandoSDWebImage, as imagens devem estar carregando em um thread separado. No entanto, fica apenas no modo paisagem no simulador do iPad.

Descrição do Problema

No modo retrato, a exibição de coleção carrega 3 células para cada linha. E não tem atraso ou atraso insignificante. No modo paisagem, a exibição de coleção carrega 4 células para cada linha. E tem óbvio atraso e queda na taxa de quadros.

Eu verifiquei com as ferramentas do instrumento com a animação principal. A taxa de quadros cai para cerca de 8 qps quando uma nova célula aparece. Não sei ao certo qual ato me traz um desempenho tão baixo para a exibição da coleção.

Espero que alguém saiba a parte dos truques.

Aqui está o código de relação

No controlador de exibição

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    ProductCollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"ProductViewCell" forIndexPath:indexPath];

    Product *tmpProduct = (Product*)_ploader.loadedProduct[indexPath.row];

    cell.product = tmpProduct;

    if (cellShouldAnimate) {
        cell.alpha = 0.0;
        [UIView animateWithDuration:0.2
                              delay:0
                            options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
                         animations:^{
                            cell.alpha = 1.0;
                         } completion:nil];
    }

    if(indexPath.row >= _ploader.loadedProduct.count - ceil((LIMIT_COUNT * 0.3)))
    {

        [_ploader loadProductsWithCompleteBlock:^(NSError *error){
            if (nil == error) {

                cellShouldAnimate = NO;
                [_collectionView reloadData];
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                    cellShouldAnimate = YES;
                });
            } else if (error.code != 1){
                #ifdef DEBUG_MODE
                    ULog(@"Error.des : %@", error.description);
                #else
                    CustomAlertView *alertView = [[CustomAlertView alloc]
                                                  initWithTitle:@"Connection Error"
                                                        message:@"Please retry."
                                                   buttonTitles:@[@"OK"]];
                    [alertView show];
                #endif
            }
        }];
    }
    return cell;

}

PrepareForReuse na collectionViewCell

- (void)prepareForReuse
{
    [super prepareForReuse];
    CGRect bounds = self.bounds;

    [_thumbnailImgView sd_cancelCurrentImageLoad];

    CGFloat labelsTotalHeight = bounds.size.height - _thumbnailImgView.frame.size.height;

    CGFloat brandToImageOffset = 2.0;
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        brandToImageOffset = 53.0;
    }

    CGFloat labelStartY = _thumbnailImgView.frame.size.height + _thumbnailImgView.frame.origin.y + brandToImageOffset;

    CGFloat nameLblHeight = labelsTotalHeight * 0.46;
    CGFloat priceLblHeight = labelsTotalHeight * 0.18;




    _brandLbl.frame = (CGRect){{15, labelStartY}, {bounds.size.width - 30, nameLblHeight}};


    CGFloat priceToNameOffset = 8.0;

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        priceToNameOffset = 18.0;
    }

    _priceLbl.frame = (CGRect){{5, labelStartY + nameLblHeight  - priceToNameOffset}, {bounds.size.width-10, priceLblHeight}};

    [_spinner stopAnimating];
    [_spinner removeFromSuperview];
    _spinner = nil;

}

Substituir o método setProduct

- (void)setProduct:(Product *)product
{

    _product = product;

    _spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    _spinner.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
    [self addSubview:_spinner];
    [_spinner startAnimating];
    _spinner.hidesWhenStopped = YES;

    // Add a spinner

    __block UIActivityIndicatorView *tmpSpinner = _spinner;
    __block UIImageView *tmpImgView = _thumbnailImgView;
    ProductImage *thumbnailImage = _product.images[0];


    [_thumbnailImgView sd_setImageWithURL:[NSURL URLWithString:thumbnailImage.mediumURL]
                                completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                                    // dismiss the spinner
                                    [tmpSpinner stopAnimating];
                                    [tmpSpinner removeFromSuperview];
                                    tmpSpinner = nil;
                                    if (nil == error) {

                                        // Resize the incoming images
                                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                                            CGFloat imageHeight = image.size.height;
                                            CGFloat imageWidth = image.size.width;

                                            CGSize newSize = tmpImgView.bounds.size;
                                            CGFloat scaleFactor = newSize.width / imageWidth;
                                            newSize.height = imageHeight * scaleFactor;

                                            UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
                                            [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
                                            UIImage *small = UIGraphicsGetImageFromCurrentImageContext();
                                            UIGraphicsEndImageContext();

                                            dispatch_async(dispatch_get_main_queue(),^{
                                                tmpImgView.image = small;
                                            });

                                        });


                                        if (cacheType == SDImageCacheTypeNone) {
                                            tmpImgView.alpha = 0.0;

                                            [UIView animateWithDuration:0.2
                                                                  delay:0
                                                                options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
                                                             animations:^{
                                                                 tmpImgView.alpha = 1.0;
                                                             } completion:nil];
                                        }

                                    } else {
                                        // loading error
                                        [tmpImgView setImage:[UIImage imageNamed:@"broken_image_small"]];
                                    }
                                }];

    _brandLbl.text = [_product.brand.name uppercaseString];

    _nameLbl.text = _product.name;
    [_nameLbl sizeToFit];


    // Format the price
    NSNumberFormatter * floatFormatter = [[NSNumberFormatter alloc] init];
    [floatFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [floatFormatter setDecimalSeparator:@"."];
    [floatFormatter setMaximumFractionDigits:2];
    [floatFormatter setMinimumFractionDigits:0];
    [floatFormatter setGroupingSeparator:@","];

    _priceLbl.text = [NSString stringWithFormat:@"$%@ USD", [floatFormatter stringFromNumber:_product.price]];

    if (_product.salePrice.intValue > 0) {
        NSString *rawStr = [NSString stringWithFormat:@"$%@ $%@ USD", [floatFormatter stringFromNumber:_product.price], [floatFormatter stringFromNumber:_product.salePrice]];

        NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:rawStr];
        // Change all the text to red first
        [string addAttribute:NSForegroundColorAttributeName
                       value:[UIColor colorWithRed:157/255.0 green:38/255.0 blue:29/255.0 alpha:1.0]
                       range:NSMakeRange(0,rawStr.length)];

        // find the first space
        NSRange firstSpace = [rawStr rangeOfString:@" "];

        // Change from zero to space to gray color
        [string addAttribute:NSForegroundColorAttributeName
                       value:_priceLbl.textColor
                       range:NSMakeRange(0, firstSpace.location)];

        [string addAttribute:NSStrikethroughStyleAttributeName
                       value:@2
                       range:NSMakeRange(0, firstSpace.location)];

        _priceLbl.attributedText = string;
    }

}