No se puede usar respondsToSelector usando ARC en Mac

83

Cuando llamo respondsToSelectoren un entorno ARC, aparece el siguiente mensaje de errorAutomatic Reference Counting Issue No known instance method for selector respondsToSelector:

Este es el encabezado

#import <AppKit/AppKit.h>


@class MTScrollView;

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


@interface MTScrollView : NSScrollView 
{

}

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

@end

Este es el archivo de implementación

#import "MTScrollView.h"

@implementation MTScrollView

@synthesize delegate;


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

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

@end

¿Alguna sugerencia sobre por qué recibo este error?

David
fuente

Respuestas:

276

Hacer que el protocolo se ajuste a NSObject

@protocol MTScrollViewDelegate <NSObject>

De lo contrario, el compilador no cree que el objeto responderá a mensajes como NSObject respondsToSelectory generará una advertencia. Tendrá éxito en tiempo de ejecución sin problemas de ninguna manera.

Jason Harwig
fuente
2
@piobyz, respondsToSelectores un método de instancia, por NSObjectlo que el sistema necesita saber que el delegado es una subclase deNSObject
David
1
@David gracias, tienes razón, además, aquí hay más información: stackoverflow.com/questions/1304176/…
Piotr Byzia
2
@piobyz en el "viejo mundo" antes de ARC, el compilador asumió que sabes lo que estás haciendo y simplemente ignoró algunas cosas en tiempo de compilación. Ahora ARC gestiona retenciones y lanzamientos por usted. Para poder asegurar que existe un método, el método debe encontrarse en su proyecto. Mientras trabaja con id, el compilador no puede encontrar ningún símbolo. Al restringir el protocolo a NSObject, ARC sabe exactamente que cualquier posible delegado contendrá "respondsToSelector". Esto garantiza la coherencia y la gestión de la memoria siempre estará bien. Las clases que no coinciden con NSObject causarán un error si se utilizan como delegado.
JackPearse
1
@piobyz: Porque respondsToSelector:es parte del protocolo NSObject. La delegatepropiedad se declara como id <MTScrollViewDelegate>, que dice solo que el delegado responde a los mensajes declarados en ese protocolo. Por lo tanto, necesita que ese protocolo se ajuste al protocolo NSObject para que el compilador sepa que se respondsToSelector:encuentra entre ellos.
Peter Hosey
1
@David: No del todo. delegateno se declara con un nombre de clase, por lo que la clase NSObject no es relevante aquí; el compilador no sabe, y aún no sabe, que esas dos cosas están relacionadas. El “NSObject” que forma parte de la solución es el protocolo NSObject , porque ahí es donde respondsToSelector:se declara. developer.apple.com/library/mac/documentation/Cocoa/Reference/…
Peter Hosey