2010-07-08 10 views
7

[Bu ilk mesajım burada (ama birçok kez cevaplara göz attım; çok yararlı bir site için herkese teşekkürler). Bu yazı ile herhangi bir büyük günah işlemek durumunda, lütfen beni affet ve doğru yönde bana işaret et.]Dış çizim yöntemi hata ayıklama için UIView veya UIWindow CGContextRef nasıl edinilir?

iPhone uygulamasında bazı karmaşık başlatma kodlarında hata ayıklamaya çalışıyorum; Hata ayıklamayı daha anlayışlı hale getirmek ve hata ayıklama tediumunu radikal bir şekilde azaltmak için bazı resimler çekmem gerekiyor.

Çizmem gereken durum aslında bir model nesne olarak mevcut değil; Başlatma sırasında biraz geçici. Özellikle büyük bir görüntüde (her hangi bir parçanın doğru/yanlış olduğunu görmeme yardımcı olmak için) bir kerede bir devletin durumunu çizebilmek istiyorum. Benim durumumda, potansiyel olarak çakışan birçok şey var ve tek bir görüntü kolayca olup bitenleri açıkça göremiyor.

Normal çizim mimarisini kullanarak ekrana çekilen statik bir görünüm oluşturmak, özel bir hata ayıklama modu ve bileşenler arasında gezinmek/vurgulamak/çizmek için ek denetimler eklersek, ancak çok fazla doğal olmayan iskele gerektirebilir. ve IMO, sorunumu hata ayıklamanın doğru yolu değil.

Peki, ne yapmayı umuyorum geçerli:

  1. almak ya floş
  2. o kullanıcıdan bazı giriş için hemen
  3. bekleme ekrana buna uygun bir CGContextRef
  4. beraberlik oluşturmak, o UIEvents
  5. tekrar 1-4 defalarca
içermezÖğe 4 neredeyse imkansız gibi görünüyor (iPhone veya iPhone simülatöründe çalışan basit C veya C++ konsol I/O gibi bir şey elde etmenin bir yolu var mı?), Bu yüzden şimdilik bunun için vazgeçtim; Çizim işlemleri arasında durmak için Xcode hata ayıklayıcısını kullanarak yerleşeceğim.

Ancak, daha fazla ilgisi, hata ayıklama çıktısının alınacağı bir UIView çizim yönteminin dışında bir CGContextRef'in nasıl alınacağıdır. Önceden geçerli bir bağlamın önbelleğe alınması, durumumda mümkün olsa bile (mümkün değil, uygulama açılışında hata ayıklama yaptığım için) işe yaramıyor. Her çizim işlemi için bağlamlar yeniden oluşturulabilirmiş gibi görünüyor; bu da beni çok fazla yüke maruz bırakıyor; Bir UIWindow'u ve belki de bir UIView'i, uygun bir çizim bağlamına referans olarak kaydedebilir ve bir referans verebilirdim. Görünüşe göre yanlış olmalıyım (ama değilse, bir görünümden veya pencereden bir bağlam nasıl elde edebilirim? Bunun için hiçbir yöntem bulamadım).

Bir çizim bağlamı oluşturmalıysam, nasıl yapabilirim? Sanırım bir bağlamla tam olarak neyin birbirine bağlı olduğunu tam olarak anlamış değilim: belirli bir ekran çıktı cihazı hakkında ne ölçüde biliyor ve ona bağlanıyor? Ekranın hangi bölümünün haritalandığını nasıl kontrol ederim? Bir bağlam yaratmak için çok az yol var gibi görünüyor ve böyle bir kontrol sağlamaya çalışmıyorlar. UIGraphicsBeginImageContext bana yardımcı olabilecek tek rutin gibi gözüküyor, ve sonuçta bir CGImage üretmek için nasıl bir çizim yapılacağını ve nasıl çizileceğini göremiyorum; Elde edilen görüntüyü ekrana nasıl alırım?

CG bağlamlarıyla ilgili bazı temel konular hakkında kafamın karıştığını görmek beni şaşırtmayacak. Umarım, bu soru o kadar basit ve açık değildir ki onu okuyan herkesi rahatsız edeceğim, fakat doğru belgeleri tamamen özlediysem, birkaç göstericiden çok memnun olurdum.

Zihinsel bant genişliğiniz ve herhangi bir yardım için teşekkür ederiz.-jar

+0

Minör zeyilname çalıştırmak için QuartzCore.framework eklemelisiniz: CGBitmapContextCreate bana UIGraphicsBeginImageContext/UIGraphicsEndImageContext olduğundan başka yardım etmek görünmüyor. iPhone'daki Quartz 2D (veya hatta Mac OS X) hakkındaki tüm yazılarım, UIView'in drawRect yönteminin dışındaki ekrana çizim yapmanın bir yolu olmadığını gösteriyor. Bunun, performansın optimize edilmesine, CGContext yaratımının karmaşıklığının gizlenmesine ya da geliştiricilerin mimarlık onaylı şekilde çizim yapmaya teşvik edilmesine ilişkin olduğunu düşünüyorum. Umarım bir şeyleri kaçırdığımı umuyorum. – jarFlooby

+0

Bağlamınızı oluşturduktan sonra görüntü olarak kaydedebilirsiniz, sonra (debug) [self presentModalViewController: specialDebugViewController] ise; UIImageView içerir ... söylediğin gibi çok iskele almayacağım. –

+0

Tüm çizim bir "CALayer" tarafından yönetiliyor gibi görünüyor. Bir katmanın ilişkili bir bağlamı vardır (ve tersi; CAContext'in bir 'layer' özelliği vardır). 'UIWindow',' _layerContext' ivar’ında bir CAContextImpl' örneğine sahiptir. Böyle bir içeriğe çekilmeye çalışmak, hala bir * geçersiz * bağlamı çizmeyi görmenizi sağlayabilir. Pencerenin içeriğini geçerli olmaya zorlayabilmeniz için masaüstü '-lockFocus' /' -lockFocusIfCanDraw' yöntemlerine eşdeğer bir değer göremiyorum. –

cevap

5

Doğrudan ekrana çizim yapamayacağınız konusunda haklısınız. Bu, bir UIView'in [view setNeedsDisplay] numaralı telefonu arayarak istendiğinde yenilenmesi için talimat verilebilir. - (void)drawRect:(CGRect)rect'u geçersiz kılarsanız, bu yenileme üzerine çağrılır. Sorununuza ilişkin önerim UIView alt sınıfını oluşturmak, hata ayıklama durumunuzu bu sınıfa yansıtmak ve durumu güncelleştirdiğinizde yenilemeyi zorlamak. Durumu yüksek bir frekansta güncelliyorsanız, görüntü yenilemesini ekran yenilemesine bağlamak için CADisplayLink kullanmalısınız. Görünüm yeniden çizilmeden önce [view setNeedsDisplay] birden çok kez ararsanız, önemli olmaz. Örneğin

:

#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 

NOT: Bu

+0

'frameInterval' aslında bir' NSInteger 'yani' 1.0f' ile ayarlanan bir başkasının 'float' olduğunu düşünmek için kod okumaya öncülük edebilir. Bunun yerine '1' kullanımı netlik için en iyisidir. –

+0

Haklısınız - bitti –

İlgili konular