Nie można użyć respondsToSelector przy użyciu ARC na Macu

83

Kiedy dzwonię respondsToSelectorw środowisku ARC, otrzymuję następujący komunikat o błędzieAutomatic Reference Counting Issue No known instance method for selector respondsToSelector:

To jest nagłówek

#import <AppKit/AppKit.h>


@class MTScrollView;

@protocol MTScrollViewDelegate
-(void)scrollViewDidScroll:(MTScrollView *)scrollView;
@end


@interface MTScrollView : NSScrollView 
{

}

@property(nonatomic, weak) id<MTScrollViewDelegate>delegate;

@end

To jest plik implementacji

#import "MTScrollView.h"

@implementation MTScrollView

@synthesize delegate;


- (void)reflectScrolledClipView:(NSClipView *)aClipView
{
    [super reflectScrolledClipView:aClipView];

    if([delegate respondsToSelector:@selector(scrollViewDidScroll:)])
    {
        [delegate scrollViewDidScroll:self];
    }
}

@end

Jakieś sugestie, dlaczego otrzymuję ten błąd?

David
źródło

Odpowiedzi:

277

Spraw, aby protokół był zgodny z NSObject

@protocol MTScrollViewDelegate <NSObject>

W przeciwnym razie kompilator nie podejrzewa, że ​​obiekt odpowie na komunikaty NSObject, takie jak respondsToSelector, i wygeneruje ostrzeżenie. To się powiedzie w czasie wykonywania bez żadnych problemów.

Jason Harwig
źródło
2
@piobyz, respondsToSelectorjest metodą instancji, NSObjectwięc system musi wiedzieć, że delegat należy do podklasyNSObject
David
1
@David dzięki, masz rację, dodatkowo tutaj trochę więcej informacji: stackoverflow.com/questions/1304176/…
Piotr Byzia
2
@piobyz w „starym świecie” przed ARC kompilator założył, że wiesz, co robisz i po prostu zignorował niektóre rzeczy w czasie kompilacji. Teraz ARC zarządza za Ciebie zachowaniami i wydaniami. Aby mieć pewność, że metody istnieją, należy ją znaleźć w projekcie. Podczas pracy z id kompilator nie może znaleźć żadnych symboli. Ograniczając protokół do NSObject, ARC wie dokładnie, że każdy możliwy delegat będzie zawierał „respondsToSelector”. Zapewnia to spójność, a zarządzanie pamięcią zawsze będzie w porządku. Klasy, które nie pasują do NSObject, spowodują błąd, jeśli zostaną użyte jako delegat.
JackPearse
1
@piobyz: Ponieważ respondsToSelector:jest częścią protokołu NSObject. delegateNieruchomość jest zadeklarowana jako id <MTScrollViewDelegate>, który mówi tylko, że reaguje delegować wiadomości zadeklarowane w tym protokole. Dlatego potrzebujesz tego protokołu, aby był zgodny z protokołem NSObject, aby kompilator wiedział, że respondsToSelector:jest wśród nich.
Peter Hosey
1
@David: Niezupełnie. delegatenie jest zadeklarowana z nazwą klasy, więc klasa NSObject nie ma tu znaczenia - kompilator nie wie i nadal nie wie, że te dwie rzeczy są ze sobą powiązane. „NSObject” będący częścią rozwiązania jest protokołem NSObject , ponieważ jest tam respondsToSelector:zadeklarowany. developer.apple.com/library/mac/documentation/Cocoa/Reference/…
Peter Hosey