2010-07-08 3 views
7

[이것은 내 첫 번째 게시물입니다 (하지만 여러 번 답변을 보았습니다. 매우 유용한 사이트 덕분입니다). 이 게시물에 큰 죄를 범하면 저를 용서해주십시오.]그리기 메서드 외부 디버깅을 위해 UIView 또는 UIWindow에서 CGContextRef를 구하는 방법은 무엇입니까?

내 iPhone 응용 프로그램에서 복잡한 시작 코드를 디버깅하려고합니다. 디버깅을 더 통찰력있게 만들고 디버그 지루함을 근본적으로 줄이려면 이미지를 그려야합니다.

내가 그릴 필요가있는 상태는 실제로 모델 객체로 존재하지 않습니다. 초기화하는 동안 다소 일시적입니다. 나는 한 번에 한 가지 상태의 비트를 그릴 수 있기를 원한다. 하나의 커다란 이미지로 모든 것을 구성하는 것이 아니라 (어떤 구성 요소가 옳고 그른지 알 수 있도록 도와주기 위해서). 필자의 경우, 잠재적으로 겹치는 부분이 많고 하나의 이미지가 어떤 일이 벌어지고 있는지 명확하게 표시 할 수 없습니다.

특수 디버그 모드를 추가하면 구성 요소를 탐색/강조 표시/그리기위한 추가 컨트롤을 만들 수 있지만 일반적인 그리기 아키텍처를 사용하여 화면에 그리는 정적 뷰를 만들 수는 있지만 부 자연스러운 스캐 폴딩이 많이 필요합니다. , 그리고 내 문제를 디버깅하는 올바른 방법은 IMO가 아닙니다.

그래서, 내가 무엇을 할 수 있도록 노력하겠습니다 것은 :

  1. 얻거나 높이
  2. 그것은 사용자로부터 어떤 입력을 즉시
  3. 대기 화면에의 적절한 CGContextRef
  4. 무승부를 만들고, UIEvents를 포함하지 않는
  5. 반복 횟수 1-4 회

항목 4는 거의 불가능한 것 같습니다 (iPhone 또는 iPhone 시뮬레이터에서 작동하는 간단한 C 또는 C++ 콘솔 I/O와 같은 것을 얻을 수있는 방법이 있습니까?) 그래서 지금은 포기했습니다. Xcode 디버거를 사용하여 드로잉 작업을 중지하는 방법으로 해결할 것입니다.

하지만 더 흥미로운 점은 디버그 출력을 그리는 UIView draw 메서드 외부에서 CGContextRef를 얻는 방법입니다. 이전에 유효한 컨텍스트를 캐싱하는 것은 비록 내 상황에서 가능할지라도 (앱 시작시 디버깅을 할 수 없기 때문에 가능하지 않음) 작동하지 않는 것으로 보입니다. 오버 헤드가 많이 발생하는 것처럼 그리기 작업마다 새로 컨텍스트를 만들 수있는 것처럼 보입니다. UIWindow 및 UIView가 저장된 것으로 가정하고 적절한 그리기 컨텍스트에 대한 참조를 제공 할 수 있습니다. 나는 틀린 것 같아 보인다. (그렇지 않다면 뷰나 윈도우에서 컨텍스트를 얻는 방법이 없다.)

따라서 드로잉 컨텍스트를 만들어야하는 경우 어떻게해야합니까? 나는 정확히 컨텍스트에 의해 정확히 묶여있는 것이 무엇인지 이해하지 못한다고 생각합니다. 특정 디스플레이 출력 장치에 대해 어느 정도 알고 있고 바인딩합니까? 컨텍스트가 매핑되는 화면의 부분을 어떻게 제어합니까? 컨텍스트를 만드는 방법은 거의없는 것처럼 보이며 그러한 제어를 제공하지 않는 것 같습니다. UIGraphicsBeginImageContext는 나를 도울 수있는 유일한 루틴처럼 보이고, CGImage를 생성하고 드로잉하는 것이 얼마나 유용한 지 알 수 없습니다. 어떻게 결과 이미지를 화면에 표시 할 수 있습니까?

나는 CG 컨텍스트와 관련된 몇 가지 기본적인 내용에 대해 혼란 스러울 것입니다. 다행히도,이 질문은 그렇게 기본적이고 명백하지 않아서 나는 그것을 읽는 모든 사람들을 짜증나게 할 것이다. 그러나 내가 옳은 문서를 놓친다면, 나는 약간의 조언을 매우 감사하게 여길 것이다.

정신적 대역폭과 도움을 주셔서 감사합니다.-jar

+0

마이너 부록을 실행하기 위해 QuartzCore.framework를 추가해야합니다 CGBitmapContextCreate 나에게 UIGraphicsBeginImageContext/UIGraphicsEndImageContext가보다 더 이상 도움이 나타나지 않습니다. iPhone (또는 Mac OS X)의 Quartz 2D에 대한 모든 저의 글은 UIView의 drawRect 메소드 밖에서 화면을 그리는 방법이 없다고 제안합니다. 나는 이것이 성능을 최적화하고, CGContext 생성의 복잡성을 숨기며, 또는 개발자가 아키텍처가 승인 한 방식으로 그리도록 권장한다고 생각합니다. 나는 아직도 내가 뭔가를 놓치기를 바란다. – jarFlooby

+0

일단 컨텍스트를 만들었 으면 이미지로 저장 한 다음 if (debug) [self presentModalViewController : specialDebugViewController]; UIImageView가 포함되어 있습니다 ... 당신이 말하는 것처럼 많은 비계 걸릴. –

+0

모든 도면이 'CALayer'에 의해 조정 된 것으로 보입니다. 레이어는 연관된 문맥을 가지고 있으며 (반대의 경우도,'CAContext'는'layer' 속성을가집니다). 'UIWindow'는'_layerContext' ivar에'CAContextImpl' 인스턴스를 가지고 있습니다. 그러한 컨텍스트에 그리려는 시도는 여전히 * 잘못된 * 컨텍스트로 그려지는 것을 볼 수 있습니다. 윈도우의 컨텍스트를 유효하게하는 데스크탑의'-lockFocus' /'-lockFocusIfCanDraw' 메소드에 해당하는 것이 없습니다. –

답변

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 

참고 :이

+0

'frameInterval'은 실제로'NSInteger'이므로'1.0f'로 설정하면 다른 사람들이 코드를 읽고 그것이 'float'이라고 생각할 수 있습니다. 명확성을 위해 대신'1 '을 사용하는 것이 가장 좋습니다. –

+0

정확함 - 완료되었습니다. –

관련 문제