2011-05-16 19 views
11

UIView's convertPoint:toView: ve convertPoint:fromView: yöntemlerinde kullanılan algoritmayı bilen var mı? Özellikle, noktayı önce pencere koordinatlarına, sonra da hedef görünümün koordinat sistemine dönüştürüp dönüştürmediklerini, ya da "from" görünümü "to" görünümünün atası olduğundan kısa bir kestirmeler yapabileceklerini biliyor musunuz?UIView, görünümler arasındaki noktaları nasıl dönüştürür?

Soruyorum, büyük olasılıkla çok sayıda görüntüye karşı bir noktayı test eden bir döngü var ve bu noktayı döngüden önce bir kez daha pencere koordinatlarına dönüştürmenin daha verimli olup olmayacağını merak ediyorum (ki bu da avantajlıdır) noktanın görüşünü döngü boyunca ve her ne olursa olsun, "fromView" argümanı için nil'i geçebileceğimi bilerek) veya ana görünümle ilgili noktayı tutmayı bilmemenin.

Bu fark, küçük olabilir, ancak kodumda çok az fark yarattığından, sistemle çalışmaktan ziyade daha çok çalışmayı tercih ederim.

cevap

13

Eh, ben algoritmanın ne olduğunu bilmek için çok daha fazla yakın değilim, ama şimdi yapmıyor ne hakkında biraz fikrim var. Yöntemleri karşılaştırmak için bir test programını kırmak için geçen gece biraz zaman geçirdim ve sonuçlar oldukça şaşırtıcıydı.

En hızlı yöntem noktayı önce pencere koordinatlarına dönüştürmek ve sonra her hedef görünüme dönüştürmekti. Şaşırtıcı olan, ne kadar daha hızlıydı: 25-27 kat daha hızlı! Ve bunun üzerine, her seferinde iki aşamalı bir dönüşüm yapmak (önce pencere koordinatlarına ve ardından hedef görünüme dönüştürmek için ayrı bir çağrı), sıfır olmayan bir görünüme sahip olan tek bir aramanın tek bir aramaya göre 10 kat daha hızlı olmasına rağmen convertPoint:fromView: argüman. Bunu gerçekten açıklayamam. Bir yöntemin iki kat daha hızlı olmasını bekleyebilirdim, ancak doğrudan yapmaktan çok iki dönüşüm yapmak daha hızlı olmamalı! (Zamanlamalarını etkilemediğinden emin olmak için, çeşitli siparişlerde de denedim.)

İşte sonuçlar (1 milyon dönüştürme, iPad 1'de çalıştırma, iOS 4.3.3):

convert from window point: 0.204297 
two-step convert through window coordinates: 0.390832 
convert from subview point: 5.020129 
incelenmek üzere aşağıdaki kodu göndeririz, ama bu sonuçlar doğruysa, benim tek tahminim dönüşüm kodu derece ve pencere/ekran koordinatlardan ve dönüştürmek için optimize edilmiş olmasıdır

bazı (çok kullanır nil olmayan bir görünüm argümanı verildiğinde iki bakış koordinat sistemleri arasında doğrudan dönüştürmek için daha yavaş yöntem. Belki de eşitsizliğin o kadar büyük olmadığı durumlar da vardır (örneğin, kimlik-olmayan dönüşümler söz konusu olduğunda olduğu gibi), fakat beklediğim şeyden ötürü, bu iki durum için daha iyi olurdu. -step dönüşüm önce pencere koordinatları ve daha sonra diğer görünümüne.

Yine, muhtemelen bu farkedilir bir program üzerinde etkisi olacak birkaç durumlar vardır, ama hiç convertPoint:toView: veya convertPoint:fromView: için sürekli çağrı bir sürü yapmak zorunda olmadığını akılda tutulması gereken bir şey. Herkes hatalarını ters kontrol etmek veya kendileri çalıştırmak umurunda varsa burada

, benim kod:

@implementation TestConvertPointViewController 

- (NSTimeInterval) timeForBlock:(void (^)())block 
{ 
    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); 
    block(); 
    return CFAbsoluteTimeGetCurrent() - startTime; 
} 

- (void) millionTimes:(void (^)(NSUInteger))block 
{ 
    for (NSUInteger i = 0; i < 1000000; i++) { 
     block(i); 
    } 
} 

- (void)loadView 
{ 
    UIView* rootView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]; 
    UIView* subview = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 250, 500)]; 
    UIView* subSubview = [[UIView alloc] initWithFrame:CGRectMake(20, 10, 130, 190)]; 
    UIView* subSubSubview = [[UIView alloc] initWithFrame:CGRectMake(50, 10, 50, 100)]; 
    [subSubview addSubview:subSubSubview]; 
    [subview addSubview:subSubview]; 
    [rootView addSubview:subview]; 
    self.view = rootView; 
} 

- (void)test 
{ 
    UIView* subview = [[self.view subviews] objectAtIndex:0]; 
    UIView* subSubview = [[subview subviews] objectAtIndex:0]; 
    UIView* subSubSubview = [[subSubview subviews] objectAtIndex:0]; 

    CGPoint testPoint = CGPointMake(10.0, 30.0); 
    NSTimeInterval time; 

    time = [self timeForBlock:^{ [self millionTimes: ^(NSUInteger i){ 
     [subSubSubview convertPoint:testPoint fromView:nil]; 
    } ]; } ]; 
    NSLog(@"convert from window point: %f", time); 

    time = [self timeForBlock:^{ [self millionTimes: ^(NSUInteger i){ 
     CGPoint rootPoint = [subview convertPoint:testPoint toView:nil]; 
     [subSubSubview convertPoint:rootPoint fromView:nil]; 
    } ]; } ]; 
    NSLog(@"two-step convert through window coordinates: %f", time); 

    time = [self timeForBlock:^{ [self millionTimes: ^(NSUInteger i){ 
     [subSubSubview convertPoint:testPoint fromView:subview]; 
    } ]; } ]; 
    NSLog(@"convert from subview point: %f", time); 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [self test]; 
} 

@end 

Ben de içinde, içinden farklı bir bir her zaman seçme 100 alt alt subviews ile test bazı önbellekleme devam ediyordu ve tek fark, muhtemelen dizi aramalarının ek yükünde hesaba katılabilirdi.

Bunun için ne yapacağımı bilmiyorum, ancak gelecekte convertPoint:fromView:'u nasıl kullanacağımı biliyorum!:-)

+0

Bu yüksek kaliteli bir yanıttır. Neden hiç kabul etmedin? – mattsven

+0

Aslında, asıl soruyu gerçekten yanıtlamadı ("Algoritma nedir?") Ve bazı ilerlemeler yapmış olsam da, başka birinin gerçek bir cevabı olacağını ummuştum, bu yüzden de soru cevaplandı. (Bu benim de kendi cevabım, bu yüzden sonuç olarak "acı çeken" sadece kendim.) –

İlgili konular