【问题标题】:setNeedsDisplayInRect redrawing entire view when using CATiledLayersetNeedsDisplayInRect 在使用 CATiledLayer 时重绘整个视图
【发布时间】:2010-01-27 05:47:55
【问题描述】:

这是我第一次发帖,请原谅stackoverflow礼仪中的任何失误。

我没有找到任何示例代码或解决我遇到的问题的任何问题,所以希望有人能对此有所了解。

我正在使用 Quartz,我有一个 CATiledLayer,我在其上绘制了几个可以单击的框。当您单击一个时,我想用蓝色轮廓重绘该框,但不重绘视图的其余部分。从我读过的 cmets 看来,一旦我在其中一个框的边界内单击,我应该使用 setNeedsDisplayInRect 而不是 setNeedsDisplay,并将脏矩形设置为该框的大小。但是,每当我的 (void)drawRect:(CGRect)rect 函数被调用时,(void)drawRect:(CGRect)rect 中的 rect 始终是我的视图的大小,无论我试图在 setNeedsDisplayInRect 中使什么 rect 无效。我认为我没有在其他任何地方调用 setNeedsDisplay 或 setNeedsDisplayInRect,但由于某种原因,整个视图无效。如果我不使用 CATiledLayer,则不会出现此问题,并且在调用 setNeedsDisplayInRect 时 DrawRect 会收到正确的 rect。

这是我的代码的简化版本:

#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>

#import "EAGLView.h"
#import "MapViewController.h"


// A class extension to declare private methods
@interface EAGLView ()

@property (nonatomic, retain) EAGLContext *context;

@end

@implementation EAGLView

+(Class)layerClass
{
    return [CATiledLayer class];
}

- (id)initWithFrame:(CGRect)frame
{
    //self.frame.size.width is 920
    //self.frame.size.height is 790
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor whiteColor];

        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        _myContext = CGBitmapContextCreate(NULL, self.frame.size.width, self.frame.size.height, 8, 4*self.frame.size.width, colorSpace, kCGImageAlphaPremultipliedFirst);
        CGColorSpaceRelease(colorSpace);

        _myLayer = CGLayerCreateWithContext(_myContext, self.frame.size, NULL);

        CATiledLayer *animLayer = (CATiledLayer *) self.layer;
        animLayer.levelsOfDetailBias = 2;
        animLayer.tileSize = CGSizeMake(1000,1000);


    }
    return self;    
}


- (void)drawRect:(CGRect)rect {
    // Drawing code, rect is always equal to the size of the view (920,720)

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    testRect = CGRectMake(0, 0, 100.0, 100.0);
    [self setNeedsDisplayInRect:testRect];
}

- (void)dealloc {

    [super dealloc];
}

@end

还有其他人遇到过这样的问题吗?这是 CATiledLayer 的限制还是我使用不正确?顺便说一句,我使用 CATiledLayer 的原因仅仅是为了在 UIScrollView 上放大和缩小时可以保持清晰的图形。 CATiledLayer 嵌入在 UIScrollView 中,但从 UIScrollView 中移除 CATiledLayer 并不能解决此问题。如果有人可以提出更好的替代方案来获得“矢量图形”缩放效果,请告诉我。我在 CATiledLayer 上花了很多时间,但我无法让它做我想做的事。

编辑:我可以删除这些行,但仍然遇到同样的问题:

CATiledLayer *animLayer = (CATiledLayer *) self.layer;
animLayer.levelsOfDetailBias = 2;
animLayer.tileSize = CGSizeMake(1000,1000);

【问题讨论】:

    标签: iphone core-graphics quartz-graphics tiles


    【解决方案1】:

    好吧,如果我添加行 animLayer.levelsOfDetail = 2;在 animLayer.levelsOfDetailBias 之后,它解决了我遇到的问题。现在正在将正确的矩形发送到 drawRect,并且在我更新时没有闪烁。我想这是一个非常简单的解决方法,我需要了解如何使用levelsofDetailBias 和levelsOfDetail。

    编辑:这实际上解决了我遇到的另一个问题,但我仍然无法将正确的dirtyRect传递给DrawRect,所以请忽略这个

    【讨论】:

    • 请将您的编辑添加为评论或更新您的问题,请不要发布 cmets 或更新作为答案
    • 转念一想,我不确定我是否真的了解发生了什么。谁能澄清一下这种情况?
    • 马杜普:嗯?这是提问者对问题的解决方案。问题的解决方案应该作为答案发布。
    • Rick:您已就自己的问题发布了答案。据我所知,它回答了这个问题,所以没有任何问题。 (有些人把这件事搞砸了,并在不回答的答案中解决了其他答案或 cmets。)
    • 对不起大家,我发布这个答案以为我已经回答了我自己的问题,但我错了,我仍然无法弄清楚如何让 drawRect 获得正确的dirtyRect。
    【解决方案2】:

    来自Apple's Q&A:“如果您调用-setNeedsDisplayInRect:-setNeedsDisplay:,整个视图将被重绘。”

    似乎-setNeedsDisplayInRect: 方法与-setNeedsDisplay: 方法相比没有任何好处。这导致人们猜测这种行为是 iOS 处理重绘时的一个错误。

    似乎没有一个干净简单的解决方案。其中的建议是将您的视图分解为几个子视图并请求仅对受影响的视图进行重绘,或者自行跟踪要重绘的区域。

    包括我在内的其他一些人也遇到了同样的问题,例如herehere

    【讨论】:

      猜你喜欢
      • 2012-04-06
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多