如何从UIView或UIWindow获取CGContextRef以调试外部draw方法?

时间:2010-07-08 10:46:51

标签: iphone debugging drawing

[这是我在这里发表的第一篇文章(但我已多次浏览答案;感谢所有人提供的非常有用的网站)。如果我在这篇文章中犯下任何重大罪行,请原谅我并指出正确的方向。]

我正在尝试在我的iPhone应用程序中调试一些复杂的启动代码;我真的需要绘制一些图像以使调试更具洞察力,并从根本上减少调试乏味。

我需要绘制的状态并不真正作为模型对象存在;在初始化期间它有些短暂。我特别希望能够一次绘制一个状态,而不是在一个大图像中绘制所有状态(以帮助我看到哪些组件是对/错)。在我的情况下,有很多可能重叠的东西,单个图像不能轻易,清楚地显示正在发生的事情。

如果我添加一个特殊的调试模式,以及导航/突出显示/绘制组件的其他控件,那么创建一个使用普通绘图架构绘制到屏幕的静态视图可能是可能的,但是它需要很多不自然的脚手架,并且不是,IMO,是调试我的问题的正确方法。

所以,我希望做的是:

  1. 获取或创建适当的CGContextRef
  2. 画在里面
  3. 立即将其冲到屏幕
  4. 等待来自用户的一些输入,不涉及UIEvents
  5. 多次重复1-4次
  6. 第4项似乎几乎是不可能的(有没有办法在iPhone或iPhone模拟器上运行简单的C或C ++控制台I / O?),所以我现在已经放弃了它;我决定只使用Xcode调试器在绘图操作之间停止。

    但更感兴趣的是如何在UIView绘制方法之外获取CGContextRef,在该方法中绘制调试输出。缓存以前有效的上下文,即使在我的情况下是可能的(不可能,因为我在app启动时调试),似乎不起作用。似乎上下文可能会为每次绘图操作重新创建,这会让我感到很费劲;我会假设一个UIWindow,也许是一个UIView,保存并可以提供对适当绘图上下文的引用。似乎我一定是错的(但如果没有,我如何从视图或窗口获取上下文?我找不到相应的方法。)

    所以,如果我必须创建绘图上下文,我该怎么做?我想我真的不太明白上下文究竟是什么联系在一起的:它在多大程度上知道并绑定到某个特定的显示输出设备?如何控制上下文映射到屏幕的哪个部分?似乎很少有创建上下文的方法,它们似乎没有提供这样的控制。 UIGraphicsBeginImageContext似乎是唯一可以帮助我的例程,我不知道如何创建和绘制一个,只有生成一个CGImage才会有用;如何将生成的图像输出到屏幕上?

    我不会惊讶地发现我对与CG上下文相关的一些基本内容感到困惑。希望这个问题不是那么基本和明显,我会讨厌所有阅读它的人,但如果我完全错过了正确的文档,我会非常感谢一些指示。

    感谢您的精神带宽和任何帮助。 -jar

1 个答案:

答案 0 :(得分:5)

你是对的,因为你不能直接画到屏幕上。话虽如此,如果你致电[view setNeedsDisplay],可以指示UIView随意刷新。如果您覆盖- (void)drawRect:(CGRect)rect,则会在刷新时调用它。我对你的问题的建议是子类UIView,在这个类上公开你的调试状态,当你更新状态时,强制刷新。如果要以较高频率更新状态,则应使用CADisplayLink将视图刷新与显示刷新联系起来。如果在重绘视图之前多次调用[view setNeedsDisplay],则无关紧要。

例如:

#import "QuartzTestView.h"
#import <QuartzCore/QuartzCore.h>

@interface QuartzTestView()

- (void)refreshView:(CADisplayLink*)displayLink;

@end


@implementation QuartzTestView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code

        CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView:)];
        [displayLink setFrameInterval:1];
        [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }
    return self;
}

- (void)refreshView:(CADisplayLink*)displayLink {
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // do updates

}

@end

注意:您必须添加QuartzCore.framework才能运行此