在UITableViewCell中的UIImageView上使用cornerRadius

时间:2013-07-11 12:33:34

标签: objective-c uitableview uiimageview quartz-graphics

我的每个UIImageView都使用UITableViewCells作为缩略图。我的代码使用SDWebImage从我的后端异步获取这些图像并加载它们,然后缓存它们。这很好。

我的UIImageView是一个50x50的正方形,在Interface Builder中创建。它的背景是不透明的白色(与我的UITableViewCell背景颜色相同,用于表现)。但是,我想使用光滑的角落来获得更好的美感。如果我这样做:

UIImageView *itemImageView = (UIImageView *)[cell viewWithTag:100];
    itemImageView.layer.cornerRadius = 2.5f;
    itemImageView.layer.masksToBounds = NO;
    itemImageView.clipsToBounds = YES;

我的tableview立即下降5-6帧,在快速滚动期间约为56 FPS(这是可以的),但是当我拖动并拉动刷新控件时,它会稍微滞后并降至40 FPS左右。如果我删除cornerRadius行,一切都很好,没有滞后。这已经在使用乐器的iPod touch 5G上进行了测试。

有没有其他方法可以为我的单元格提供一个舍入UIImageView而不会受到性能影响?我已经对cellForRowAtIndexPath进行了优化,在没有cornerRadius的情况下进行快速滚动时得到56-59 FPS。

4 个答案:

答案 0 :(得分:31)

是的,那是因为cornerRadius和clipToBounds需要屏幕外渲染,我建议你从我的question之一阅读这些答案。我还引用了你应该看到的两个WWDC会话。
你可以做的最好的事情是在下载后立即抓取图像,并在另一个线程上发送一个围绕图像的方法。最好是处理图像而不是图像视图。

// Get your image somehow
UIImage *image = [UIImage imageNamed:@"image.jpg"];

// Begin a new image that will be the new image with the rounded corners 
// (here with the size of an UIImageView)
 UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);

 // Add a clip before drawing anything, in the shape of an rounded rect
  [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds 
                        cornerRadius:10.0] addClip];
 // Draw your image
[image drawInRect:imageView.bounds];

 // Get the image, here setting the UIImageView image
  imageView.image = UIGraphicsGetImageFromCurrentImageContext();

 // Lets forget about that we were drawing
  UIGraphicsEndImageContext();

抓取方法here 您还可以子类化tableviewcell并覆盖drawRect方法。
肮脏但非常有效的方法是在photoshop中使用内部alpha和单元格背景的匹配颜色绘制一个蒙版,并在带有图像的那个上添加另一个不具有透明背景颜色的imageView。

答案 1 :(得分:7)

还有另一个很好的解决方案。我在我的项目中做了几次。如果你想创建一个圆角或其他东西,你可以在主图像前面使用封面图像。

  

例如,您想要制作圆角。在这种情况下,您需要一个方形图像层,中间有一个切出的圆圈。

通过使用此方法,您可以在UITableViewUICollectionView内滚动60fps。因为此方法不需要屏幕外渲染来自定义UIImageView(如头像等)。

答案 2 :(得分:5)

非阻塞解决方案

作为Andrea的回复的后续,这是一个将在后台运行他的代码的函数。

+ (void)roundedImage:(UIImage *)image
          completion:(void (^)(UIImage *image))completion {
    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Begin a new image that will be the new image with the rounded corners
        // (here with the size of an UIImageView)
        UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
        CGRect rect = CGRectMake(0, 0, image.size.width,image.size.height);

        // Add a clip before drawing anything, in the shape of an rounded rect
        [[UIBezierPath bezierPathWithRoundedRect:rect
                                    cornerRadius:image.size.width/2] addClip];
        // Draw your image
        [image drawInRect:rect];

        // Get the image, here setting the UIImageView image
        UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();

        // Lets forget about that we were drawing
        UIGraphicsEndImageContext();
        dispatch_async( dispatch_get_main_queue(), ^{
            if (completion) {
                completion(roundedImage);
            }
        });
    });
}

答案 3 :(得分:1)

Swift 3版本的开发者3124的回答

$result = test("mycluster");

$count = 0;
foreach($result['items'] as $item) {
    $count += isset($item['Hosts']) && isset($item['Hosts']['host_name']) ? 1 : 0;
}
print_r($count); // will print 3