2009-06-22 23 views
10

Üçüncü sınıf bir temsilci olarak davranabilen iki sınıfım var ve her ikisi de isteğe bağlı yöntemlerden oluşan resmi bir protokol uygular. Sınıflardan biri her şeyi yerine getirir, diğeri ise sadece önemsediğim birkaç yöntemi uygular. Ancak, ikinci sınıfın üçüncü sınıf için temsilci olarak hareket ettiğim çalışma zamanında ve üçüncü sınıf bu temsilci üzerinde seçilmemiş olan isteğe bağlı yöntemlerden birini çağırmayı sona erdirirken, temelde "Hedef buna yanıt vermiyor" şeklinde bir çalışma zamanı hatası alıyorum mesaj seçici. " Amaç-c'nin bu vakayı doğru bir şekilde ele aldığını ve bu yöntem aslında sınıfta tanımlanmamışsa hiçbir şey yapamayacağını düşündüm. Kaybettiğim bir şey olabilir mi?Neden uygulanamaz isteğe bağlı protokol yöntemleri, bu yöntem obj-c'de çağrıldığında çalışma zamanı hatalarına neden olur?

if ([delegate respondsToSelector:@selector(optionalMethod)]) 
    [delegate optionalMethod]; 

cevap

33

, bunu çağırmadan önce seçicinin yanıt emin olmak gerekir Söz konusu yöntem - daha sonra aranan kişi, nesnenin aramadan önce yöntemi uygulayıp uygulamadığını kontrol etmelidir (aksi halde fark ettiğinizde kilitlenirsiniz). Bunlar NSObject HOM kategoriler yararlı olabilir:

@implementation NSObject (Extensions) 

- (id)performSelectorIfResponds:(SEL)aSelector 
{ 
    if ([self respondsToSelector:aSelector]) { 
     return [self performSelector:aSelector]; 
    } 
    return NULL; 
} 

- (id)performSelectorIfResponds:(SEL)aSelector withObject:(id)anObject 
{ 
    if ([self respondsToSelector:aSelector]) { 
     return [self performSelector:aSelector withObject:anObject]; 
    } 
    return NULL; 
} 

@end 

Sonra sadece yapabilirsiniz:

[delegate performSelectorIfResponds:@selector(optionalMethod)]; 
+2

ama ben eklemeniz gerekmez umuyordum Bütün kodlar kontrol ediliyorsa. İşaretçi için teşekkürler. – Kevlar

10

Opsiyonel protokol yöntemleri basitçe uygulamak zorunda değildir protokolü uygulayan nesne anlamına gelir: Eğer temsilci için opsiyonel bir yöntem çağırdığınızda

+0

güzel öneri :) – Kevlar

+0

........ Whats HOM? – bandejapaisa

+0

HOM = Daha Yüksek Sırada Mesajlaşma. –

1

Blokları daha iyi bir çözüm sağlayabilir. Onlar şartlı verilen bir yöntem uygulamasının varlığına dayalı herhangi bir kod gerçekleştirmek için izin: NSObject bu ek kullanarak

-(void) performBlock:(void (^)(void))block ifRespondsTo:(SEL) aSelector{ 
    if ([self respondsToSelector:aSelector]) { 
     block(); 
    } 
} 

, koşullu olursa olsun sahip olabilir kaç parametreleri, herhangi @optional yöntemi yürütebilirsiniz .

kafanızın neler olduğunu sarılı olsun bir kez How to safely send @optional protocol messages that might not be implemented

4

Bu Bloklar çözüm, iyi çalışıyor bakınız. Bir BOOL sonucunu ekledim çünkü koşullu olarak birkaç isteğe bağlı yöntemden birini çalıştırmak istedim. Bu çözümü uygulamak için bazı ipuçları:

İlk olarak, henüz Uzantı/Kategoriler ile karşılaşmadıysanız, bunu yalnızca sınıfınızın en üst düzeyine ekleyerek var olan sınıf tanımını OUTSIDE. Bunu koyduğunuz yere dayalı bir kamu ya da özel uzantı olacaktır.

@implementation NSObject (Extensions) 
// add block-based execution of optional protocol messages 
-(BOOL) performBlock:(void (^)(void))block ifRespondsTo:(SEL) aSelector 
{ 
    if ([self respondsToSelector:aSelector]) { 
     block(); 
     return YES; 
    } 
    return NO; 
} 
@end 

İkincisi, burada kendi kodundan onu aramak nasıl: En protokol yöntemi için her parametre isimlerini içeren: Param2: ParamN

BOOL b = [(NSObject*)self.delegate performBlock:^{ 
    // code to run if the protocol method is implemented 
} 
ifRespondsTo:@selector(Param1:Param2:ParamN:)]; 

Param1 değiştirin. Her biri bir kolon ile bitmelidir. son satır şu şekilde görünecektir

-(void)dosomething:(id)blah withObj:(id)blah2 andWithObj(id)blah3;

: gibi Yani protokol yöntemi görünüyorsa

ifRespondsTo:@selector(dosomething:withObj:andWithObj:)];

eskisi kadar şüpheli
İlgili konular