【问题标题】:CALayer setCornerRadius lag in UITableView in iPad?CALayer setCornerRadius 在 iPad 的 UITableView 中滞后?
【发布时间】:2012-06-03 07:04:48
【问题描述】:

我正在为 iPhone/iPad 制作一个通用应用程序,似乎下面的代码有很多滞后:

CALayer *imageLayer = [cell.myImageView layer];
[imageLayer setMasksToBounds:YES];
[imageLayer setCornerRadius:6.0];

奇怪的是,iPhone 版本没有滞后,而 iPad 版本有一些滞后。我对两种设备之间的代码没有区别,但是如果我注释掉上面的代码,那么这两种设备似乎都很好。但是,我仍然想要 UIImageView 上的圆角,“myImageView”。

我只在第一个单元格初始化期间在 cellForRowAtIndexPath 中执行那段代码,因为我的所有单元格都是相同的。

有人知道为什么会这样吗?

谢谢!

【问题讨论】:

  • 我建议您向我们展示整个 cellforrowatindexpath 数据源方法源代码

标签: ios ipad uitableview lag


【解决方案1】:

CALayer 操作使用大量 cpu 功率来绘制。

因此,最好的解决方案是使用核心图形绘制图像。 Loren Brichter 是第一个向我们展示如何:

这是他的 ABTableViewCell 标头 (.h) 文件的代码

// Copyright (c) 2008 Loren Brichter
// 
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//  ABTableViewCell.h
//
//  Created by Loren Brichter
//  Copyright 2008 Loren Brichter. All rights reserved.
//

#import <UIKit/UIKit.h>

// to use: subclass ABTableViewCell and implement -drawContentView:

@interface ABTableViewCell : UITableViewCell
{
    UIView *contentView;
}

- (void)drawContentView:(CGRect)r; // subclasses should implement

@end

这里是 impelementation (.m) 文件的代码:

// Copyright (c) 2008 Loren Brichter
// 
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//  ABTableViewCell.m
//
//  Created by Loren Brichter
//  Copyright 2008 Loren Brichter. All rights reserved.
// 

#import "ABTableViewCell.h"

@interface ABTableViewCellView : UIView
@end

@implementation ABTableViewCellView

- (void)drawRect:(CGRect)r
{
    [(ABTableViewCell *)[self superview] drawContentView:r];
}

@end



@implementation ABTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
        contentView = [[ABTableViewCellView alloc]initWithFrame:CGRectZero];
        contentView.opaque = YES;
        [self addSubview:contentView];
    }
    return self;
}


- (void)setFrame:(CGRect)f
{
    [super setFrame:f];
    CGRect b = [self bounds];
    b.size.height -= 1; // leave room for the seperator line
    [contentView setFrame:b];
}

- (void)setNeedsDisplay
{
    [super setNeedsDisplay];
    [contentView setNeedsDisplay];
}

- (void)drawContentView:(CGRect)r
{
    // subclasses should implement this
}

@end

现在您需要做的是使用 Core Graphics 在 drawContentView 方法中绘制您的单元格。

这是我在正在开发的应用程序中使用的部分代码:

    CALayer *cellLayer = [[CALayer alloc] init];
    CGRect cellFrame = self.bounds;
    CGRect layerFrame = CGRectInset(cellFrame, 3, 3);

    cellLayer.frame = cellFrame;
    cellLayer.contentsScale = [[UIScreen mainScreen] scale];

     //round corners in Core Graphics (much faster than using the CALayer cornerRadius)
     UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [[UIScreen mainScreen] scale]);

     CGContextRef imgContext = UIGraphicsGetCurrentContext();

    CGContextSaveGState(imgContext);  
    //create the rounded rectangle to draw the image in
    CGPathRef clippingPath = [UIBezierPath bezierPathWithRoundedRect:layerFrame cornerRadius:6.0f].CGPath;
    CGContextAddPath(imgContext, clippingPath);
    CGContextClip(imgContext);

CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)[NSData dataWithContentsOfFile:ImageName]);
            CGImageRef imageRef = CGImageCreateWithJPEGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);
            CGDataProviderRelease(imgDataProvider);
            CGContextDrawImage (imgContext, layerFrame, imageRef);
            CGImageRelease(imageRef);

CGContextRestoreGState(imgContext);

        //draw white outline
        CGPathRef path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(cellFrame, 3, 3) cornerRadius:6.0f].CGPath;
        CGContextAddPath(imgContext, path);
        CGContextSetLineWidth(imgContext, 2.0);
        CGContextSetRGBStrokeColor(imgContext,1,1,1,1);
        CGContextStrokePath(imgContext);

        // Get the image from the context
        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();


        cellLayer.contents = (__bridge id)img.CGImage;

要使用自定义单元格,您需要以这种方式在 tableView CellForRowAtIndexPath 数据源方法中对其进行初始化:

    static NSString *CellIdentifier = @"TableCell";

    ABTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {        
        cell = [[ABTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
}

还请记住,由于您正在进行自定义绘图,因此当您使用以下方法修改自己的内容时,您需要始终重新调整单元格视图:

[cell setNeedsDisplay];

【讨论】:

  • 嗯,不,这并没有太大帮助。还是有很多滞后。即使我在此视图中显示我的 Game Center 模式视图,显示该成就视图的动画也有滞后。我的应用程序中没有其他视图有这个问题,这真的很奇怪。我还能优化什么?
  • 如果不设置cell Image,你测的是多少FPS?只是想看看问题出在哪里......我会删除整个个人资料图片部分并测量
  • 再次查看我的整个问题和原始帖子,我更改了所有内容:P 另外,如果您能足够友善并摆脱答案中的代码,那就太好了,因为我宁愿没有那么容易看到代码,因为它最终会在我的应用程序中! :)
  • 谢谢。知道为什么 CALayer 会导致所有延迟吗?
  • 哇,为了在 UITableViewCell 中的 UIImageView 上获得圆角,这些代码真的是必需的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-22
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多