Bir seçicinin, bir protokolde objç içerisinde yer almasına nasıl karar verilir? Teşekkürler

Bazı UITableViewDelegate yöntemini bir nedenden ötürü başka bir nesneye iletmek istiyorum。 İşte yazdığım kod, ancak UITableViewDelegate'de çok fazla yöntem olduğu için.

- (id)forwardingTargetForSelector:(SEL)aSelector
{    
    NSString* selector = NSStringFromSelector(aSelector);
    if ([selector isEqualToString:@"tableView:didSelectRowAtIndexPath:"])
    {
        return self.outDelegate;
    }
    else
    {
        return [super forwardingTargetForSelector:aSelector];

    }
}

Ve bunu yapmak için daha iyi bir çözüm olduğunu düşünüyorum.Aşağıdaki gibi yapabilirim, bir Seçicinin nasıl test edileceği Protolde tanımlanmış veya değil

- (id)forwardingTargetForSelector:(SEL)aSelector
{    
    if (**aSelector is Defined in aProtocol**)
    {
        return self.outDelegate;
    }
    else
    {
        return [super forwardingTargetForSelector:aSelector];

    }
}
2
@ stonesam92, çünkü UITableViewDelegate, UIScrollViewDelegate'e uygundur ve bu iki protokolü farklı temsilci olarak ayırmak istiyorum.
katma yazar ximmyxiao, kaynak
@ stonesam92, aslında bir tablo görünümü olarak bir çekme ve yenileme görünümü yazıyordu. Bu yüzden refreshView içinde UIScrollViewDelegate ile sth yapmak ve denetleyicide UITableViewDelegate şeyler yapmak zorunda, bu yüzden bu iki delege ayırmak istiyorum, belki de iyi bir fikir değil :)
katma yazar ximmyxiao, kaynak
@ stonesam92, aslında bir tablo görünümü olarak bir çekme ve yenileme görünümü yazıyordu. Bu yüzden refreshView içinde UIScrollViewDelegate ile sth yapmak ve denetleyicide UITableViewDelegate şeyler yapmak zorunda, bu yüzden bu iki delege ayırmak istiyorum, belki de iyi bir fikir değil :)
katma yazar ximmyxiao, kaynak
Çalışma zamanına bırakmanız gerekebilir. bakınız:
katma yazar Jeffery Thomas, kaynak
Bu arada, işaretçi eşitliği seçiciler için çalışır: @selector (tableView: didSelectRowAtIndexPath :) == aSelector .
katma yazar Jeffery Thomas, kaynak
Neden sadece ilk olarak UITableView 'in temsilcisini' gerçek 'temsilci ( self.outDelegate ) olarak ayarlamıyorsunuz?
katma yazar stonesam92, kaynak

9 cevap

protocol_copyMethodDescriptionList öğesini kullanarak bir protokoldeki yöntemlerin C dizisini alabilirsiniz:

int numOfMethods;
struct objc_method_description * method_description_list;
method_description_list = protocol_copyMethodDescriptionList(@protocol(protocolName), 
    YES, YES, &numOfMethods)

Dizideki açıklamaların sayısı şimdi numOfMethods değişkeninde saklanır. Daha sonra bu diziyi yineleyebilir ve seçicileri dizgelere dönüştürmek yerine, her yöntem için seçicinin geçerli seçiciye eşit olup olmadığını kontrol edebilirsiniz:

for (int i=0; i

İşiniz bittiğinde kapladığı hafızayı geri kazanmak için ücretsiz (method_description_list) yapmanız gerektiğini unutmayın.

Her zaman forwardingTargetForSelector: çağrıldığında onu yeniden oluşturmanın ve serbest bırakmanın bir anlamı yoktur, bu nedenle onu bir iVar'a dönüştürmek ve init içinde oluşturmak gibi bir şey yapmak isteyebilirsiniz ve sonra free bunu dealloc içinde yapın, çünkü protokol bu nesnenin kullanım ömrü boyunca değişmeyebilir.

2
katma
thanks @ stonesam92, bu iyi çalışıyor
katma yazar ximmyxiao, kaynak
Burada işleri biraz yeniden yapılandırmanız gerekir, sonunda free (method_description_list) yazmanız gerekir, bu nedenle ortada [süper forwardingTargetForSelector: aSelector] döndüremezsiniz.
katma yazar Jeffery Thomas, kaynak
NOT: sel_isEqual == ile eşdeğerdir.
katma yazar Jeffery Thomas, kaynak
Her yöntem çağrısında listenin yeniden oluşturulması gerekmeyeceğinden, diziyi init ve sonra da free dealloc , ancak yayınlamayı bu açık yapmak için düzenleyeceğim
katma yazar stonesam92, kaynak

protocol_copyMethodDescriptionList öğesini kullanarak bir protokoldeki yöntemlerin C dizisini alabilirsiniz:

int numOfMethods;
struct objc_method_description * method_description_list;
method_description_list = protocol_copyMethodDescriptionList(@protocol(protocolName), 
    YES, YES, &numOfMethods)

Dizideki açıklamaların sayısı şimdi numOfMethods değişkeninde saklanır. Daha sonra bu diziyi yineleyebilir ve seçicileri dizgelere dönüştürmek yerine, her yöntem için seçicinin geçerli seçiciye eşit olup olmadığını kontrol edebilirsiniz:

for (int i=0; i

İşiniz bittiğinde kapladığı hafızayı geri kazanmak için ücretsiz (method_description_list) yapmanız gerektiğini unutmayın.

Her zaman forwardingTargetForSelector: çağrıldığında onu yeniden oluşturmanın ve serbest bırakmanın bir anlamı yoktur, bu nedenle onu bir iVar'a dönüştürmek ve init içinde oluşturmak gibi bir şey yapmak isteyebilirsiniz ve sonra free bunu dealloc içinde yapın, çünkü protokol bu nesnenin kullanım ömrü boyunca değişmeyebilir.

2
katma
thanks @ stonesam92, bu iyi çalışıyor
katma yazar ximmyxiao, kaynak
Burada işleri biraz yeniden yapılandırmanız gerekir, sonunda free (method_description_list) yazmanız gerekir, bu nedenle ortada [süper forwardingTargetForSelector: aSelector] döndüremezsiniz.
katma yazar Jeffery Thomas, kaynak
NOT: sel_isEqual == ile eşdeğerdir.
katma yazar Jeffery Thomas, kaynak
Her yöntem çağrısında listenin yeniden oluşturulması gerekmeyeceğinden, diziyi init ve sonra da free dealloc , ancak yayınlamayı bu açık yapmak için düzenleyeceğim
katma yazar stonesam92, kaynak

Bir temsilcinin seçiciye sahip olup olmadığını kontrol etmek için respondsToSelector: kullanabilirsiniz.

Ayrıca, conformsToProtocol: 'ı respondsToSelector: as - ile birlikte kullanabilirsiniz

if([delegate conformsToProtocol:@protocol(MyProtocol)] && [delegate respondsToSelector: @selector(aMethod)])
    {
        //send message;
    }
1
katma
teşekkürler, ama bu iki koşulun yeterli olmadığını düşünüyorum, çünkü iletmek istemediğim bazı seçiciler olabilir, bu yüzden ilk önce protokolde bir hakim seçiciye sahip olduğumu düşünüyorum
katma yazar ximmyxiao, kaynak
Bu (ve çoğu diğer cevaplar) aslında soruyu ele almaz. OP, temsilcinin verilen bir protokole uygun olup olmadığını kontrol etmek istemez, onlar (bilinmeyen bir nedenden dolayı) gelen bir mesajın bir protokolün parçası olup olmadığını kontrol etmek ister ve eğer öyleyse mesajı başka bir nesneye iletmek ister () self.outDelegate ). Bu cevap, temsilcinin yanıtladığı her iletiyi iletecektir ( açıklama ve muhtemelen init gibi tüm standart NSObject yöntemlerini içerir)
katma yazar stonesam92, kaynak

Bir temsilcinin seçiciye sahip olup olmadığını kontrol etmek için respondsToSelector: kullanabilirsiniz.

Ayrıca, conformsToProtocol: 'ı respondsToSelector: as - ile birlikte kullanabilirsiniz

if([delegate conformsToProtocol:@protocol(MyProtocol)] && [delegate respondsToSelector: @selector(aMethod)])
    {
        //send message;
    }
1
katma
teşekkürler, ama bu iki koşulun yeterli olmadığını düşünüyorum, çünkü iletmek istemediğim bazı seçiciler olabilir, bu yüzden ilk önce protokolde bir hakim seçiciye sahip olduğumu düşünüyorum
katma yazar ximmyxiao, kaynak
Bu (ve çoğu diğer cevaplar) aslında soruyu ele almaz. OP, temsilcinin verilen bir protokole uygun olup olmadığını kontrol etmek istemez, onlar (bilinmeyen bir nedenden dolayı) gelen bir mesajın bir protokolün parçası olup olmadığını kontrol etmek ister ve eğer öyleyse mesajı başka bir nesneye iletmek ister () self.outDelegate ). Bu cevap, temsilcinin yanıtladığı her iletiyi iletecektir ( açıklama ve muhtemelen init gibi tüm standart NSObject yöntemlerini içerir)
katma yazar stonesam92, kaynak

Bunun gibi kontrol et -

if([delegate conformsToProtocol:@protocol(yourProtocolName)])
{
    //Do Something
}
0
katma
Müthiş nedir? Lütfen cevabınıza ayrıntı ekleyin ve sadece kod yazmayın. Kullanıcı olmasının nedeni, bu kodun ne yaptığını bilmediğinden, açıklanmasını ister. Lütfen ayrıntı ekleyin. BTW Bunun ne olduğunu tam olarak biliyorum.
katma yazar Popeye, kaynak

Bunun gibi kontrol et -

if([delegate conformsToProtocol:@protocol(yourProtocolName)])
{
    //Do Something
}
0
katma
Müthiş nedir? Lütfen cevabınıza ayrıntı ekleyin ve sadece kod yazmayın. Kullanıcı olmasının nedeni, bu kodun ne yaptığını bilmediğinden, açıklanmasını ister. Lütfen ayrıntı ekleyin. BTW Bunun ne olduğunu tam olarak biliyorum.
katma yazar Popeye, kaynak

UIKit'te, Apple bunu UIUserNotificationRestrictedAlertViewProxy'nin yanıtlarındaToSelector uygulamasında isAlertViewDelegateMethod öğesini kontrol etmek için yapar, ancak kodunu UITableViewDelegate ile çalışacak şekilde değiştirdim:

BOOL isTableViewDelegateMethod(SEL selector) {
    struct objc_method_description desc;
    desc = protocol_getMethodDescription(@protocol(UITableViewDelegate), selector, NO, YES);
    if(desc.name){
        return YES;
    }
    desc = protocol_getMethodDescription(@protocol(UITableViewDelegate), selector, YES, YES);
    if(desc.name){
        return YES;
    }
    return NO;
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{    
    if (isTableViewDelegateMethod(aSelector))
    {
        return self.outDelegate;
    }
    else
    {
        return [super forwardingTargetForSelector:aSelector];

    }
}

Ayrıca, tablo görünümlerinde iki delegeye sahip olduğundan UITableViewDataSource'u da kontrol etmek isteyebilirsiniz.

0
katma

UIKit'te, Apple bunu UIUserNotificationRestrictedAlertViewProxy'nin yanıtlarındaToSelector uygulamasında isAlertViewDelegateMethod öğesini kontrol etmek için yapar, ancak kodunu UITableViewDelegate ile çalışacak şekilde değiştirdim:

BOOL isTableViewDelegateMethod(SEL selector) {
    struct objc_method_description desc;
    desc = protocol_getMethodDescription(@protocol(UITableViewDelegate), selector, NO, YES);
    if(desc.name){
        return YES;
    }
    desc = protocol_getMethodDescription(@protocol(UITableViewDelegate), selector, YES, YES);
    if(desc.name){
        return YES;
    }
    return NO;
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{    
    if (isTableViewDelegateMethod(aSelector))
    {
        return self.outDelegate;
    }
    else
    {
        return [super forwardingTargetForSelector:aSelector];

    }
}

Ayrıca, tablo görünümlerinde iki delegeye sahip olduğundan UITableViewDataSource'u da kontrol etmek isteyebilirsiniz.

0
katma

Bu tür forwardInvocation ve delegate yöntemi doğrulamasını yapmak istediğinizde "responseToSelector" ve "conformsToProtocol" yöntemlerini kullanabilir ve ilgili ForwardInvocation işlemini yapabilirsiniz.

0
katma