为什么我不能画一个循环? (在iPhone中使用UIView)

时间:2010-04-11 16:54:06

标签: objective-c iphone loops quartz-graphics

我可以用这个来画很多东西:

NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"dummy2.png" ofType:nil];
UIImage *img = [UIImage imageWithContentsOfFile:imagePath];
image = CGImageRetain(img.CGImage);

CGRect imageRect;

double x = 0;
double y = 0;

for (int k=0; k<someValue; k++) {
    x += k;
            y += k;

        imageRect.origin = CGPointMake(x, y);
        imageRect.size = CGSizeMake(25, 25);    
        CGContextDrawImage(UIGraphicsGetCurrentContext(), imageRect, image);
    }
}

CGImageRelease(img.CGImage);

所以,它有效,所以,我将它放入命令对象的execute方法中。然后,我想做类似的事情,但这一次,我的执行方法只做这个:

NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"dummy2.png" ofType:nil];
UIImage *img = [UIImage imageWithContentsOfFile:imagePath];
image = CGImageRetain(img.CGImage);

CGRect imageRect;

double x = inComingX;
double y = inComingY;

 imageRect.origin = CGPointMake(x, y);
        imageRect.size = CGSizeMake(25, 25);    
        CGContextDrawImage(UIGraphicsGetCurrentContext(), imageRect, image);

    CGImageRelease(img.CGImage);

这次,这也是一个Command,它是execute方法。但我接受了for循环。我将有另一种方法将inComingX和inComingY传递给我的Command对象。

我的绘图方法只是执行我在drawingEngine中传递的Cmd:

-(void)drawInContext:(CGContextRef)context
{
    [self.cmdToBeExecuted execute];
}

我还有assign方法来分配命令:

-(void)assignCmd:(Command* )cmd{
    self.cmdToBeExecuted = cmd;

}

这就是我调用drawingEngine的方式

for(int k=0; k<5; k++){
    [self.drawingEngine assignCmd:[DrawingCmd setDrawingInformation:(10*k):0:@"dummy.png"]];
    [self.drawingEngine setNeedsDisplay];
}

它可以画画,但可悲的是它只画了最后一个。为什么?以及如何解决它?我可以在我的第一个代码中绘制所有内容,但是在我将循环放在外面并在最后一个代码中使用循环之后,它只绘制最后一个代码。 Plz帮助

1 个答案:

答案 0 :(得分:4)

那是因为setNeedsDisplay实际上并未调用drawRect:。它只是在下一个“方便”时间安排视图重绘,这可能是下一次,应用程序重新进入运行循环。由于在每次调用赋值函数时都会覆盖记住的命令对象,到时候实际调用drawRect:,只有最后分配的命令可用并且将被绘制。

更好的方法是:记住要绘制的所有命令,而不是最后一个,比如在数组中,例如:

@interface MyCanvas {
    ...
    NSMutableArray* commandList;
    ...
}

并向该数组添加命令,而不是分配单个命令成员:

-(void) addCommand:(Command*) cmd {
    [self.commandList addObject: cmd];
}

然后应在draw方法

中处理这些命令
for( Command* cmd in self.commandList ) {

    [cmd execute ...];
}

或者,您可以定义“复杂”命令,其中包含多个绘图步骤。

编辑以回答评论中的问题):您的原始代码确实有效,因为它可以在适当的单一调用中的所有位置完成工作draw方法。您的上一个代码在运行时根本不会绘制任何内容。它只记得(通过命令对象)必须要做的事情,并通知视图,它应该在下一个方便的场合重新绘制 。重要的是要注意,setNeedsDisplay导致任何重新绘制直接完成。它只是将视图标记为“脏”,稍后将在Cocoa运行时被其他代码拾取。

您的代码中还有另一件事我觉得有点可疑:您的方法drawInContext:采用了一个上下文参数,它被简单地忽略了。它既不会传递给命令对象的execute方法,也不会在实例变量中安装为某种“当前”绘图上下文或某些东西。如果您希望drawRect:(或命令的execute方法)中的代码实际使用该上下文,则必须将其传递给应该使用它的任何人。