Impossible d'utiliser respondsToSelector avec ARC sur Mac

83

Lorsque j'appelle respondsToSelectordans un environnement ARC, j'obtiens le message d'erreur suivantAutomatic Reference Counting Issue No known instance method for selector respondsToSelector:

C'est l'en-tête

#import <AppKit/AppKit.h>


@class MTScrollView;

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


@interface MTScrollView : NSScrollView 
{

}

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

@end

Ceci est le fichier d'implémentation

#import "MTScrollView.h"

@implementation MTScrollView

@synthesize delegate;


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

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

@end

Des suggestions sur pourquoi j'obtiens cette erreur?

David
la source

Réponses:

276

Rendre le protocole conforme à NSObject

@protocol MTScrollViewDelegate <NSObject>

Sinon, le compilateur ne pense pas que l'objet répondra aux messages NSObject comme respondsToSelector, et générera un avertissement. Il réussira à l'exécution sans problèmes de toute façon.

Jason Harwig
la source
2
@piobyz, respondsToSelectorest une méthode d'instance de NSObjectdonc le système doit savoir que le délégué fait partie de la sous-classe deNSObject
David
1
@David merci, vous avez raison, voici également quelques informations supplémentaires: stackoverflow.com/questions/1304176/...
Piotr Byzia
2
@piobyz dans le "vieux monde" avant ARC, le compilateur supposait que vous saviez ce que vous faisiez et ignorait simplement certaines choses au moment de la compilation. ARC gère désormais les retenues et les versions pour vous. Pour être en mesure de s'assurer qu'une méthode existe, la méthode doit être trouvée dans votre projet. En travaillant avec id, le compilateur ne trouve aucun symbole. En restreignant le protocole à NSObject ARC sait exactement que tout éventuel délégué contiendra "respondsToSelector". Cela garantit la cohérence et la gestion de votre mémoire sera toujours correcte. Les classes qui ne correspondent pas à NSObject provoquent une erreur si elles sont utilisées comme délégué.
JackPearse
1
@piobyz: Parce que respondsToSelector:fait partie du protocole NSObject. La delegatepropriété est déclarée comme id <MTScrollViewDelegate>, ce qui indique uniquement que le délégué répond aux messages déclarés dans ce protocole. Ainsi, vous avez besoin que ce protocole soit conforme au protocole NSObject pour que le compilateur sache qu'il en respondsToSelector:fait partie.
Peter Hosey
1
@David: Pas tout à fait. delegaten'est pas déclarée avec un nom de classe, donc la classe NSObject n'est pas pertinente ici - le compilateur ne sait pas et ne sait toujours pas que ces deux choses sont liées. Le «NSObject» qui fait partie de la solution est le protocole NSObject , car c'est là que respondsToSelector:est déclaré. developer.apple.com/library/mac/documentation/Cocoa/Reference/…
Peter Hosey