83

When I call respondsToSelector in an ARC environment, I get the following error message Automatic Reference Counting Issue No known instance method for selector respondsToSelector:

This is the header

#import <AppKit/AppKit.h>


@class MTScrollView;

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


@interface MTScrollView : NSScrollView 
{

}

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

@end

This is the implementation file

#import "MTScrollView.h"

@implementation MTScrollView

@synthesize delegate;


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

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

@end

Any suggestions on why I am getting this error?

Jeff Kelley
  • 19,021
  • 6
  • 70
  • 80
David
  • 14,205
  • 20
  • 97
  • 144

2 Answers2

278

Make the protocol conform to NSObject

@protocol MTScrollViewDelegate <NSObject>

Otherwise the compiler doesn't think that the object will respond to NSObject messages like respondsToSelector, and will generate a warning. It will succeed at runtime without issues either way.

Jason Harwig
  • 43,743
  • 5
  • 43
  • 44
  • Could anyone explain why conforming to NSObject fixes the issue? – Piotr Byzia Nov 15 '11 at 18:27
  • 2
    @piobyz, `respondsToSelector` is an instance method of `NSObject` so the system needs to know that the delegate is some of subclass of `NSObject` – David Nov 17 '11 at 12:59
  • 1
    @David thanks, you're right, additionally here is some more info: http://stackoverflow.com/questions/1304176/objective-c-difference-between-id-and-void/1304277#1304277 – Piotr Byzia Nov 17 '11 at 13:49
  • 2
    @piobyz in the "old world" before ARC the compiler assumed you know what you are doing and simply ignored some stuff at compile time. Now ARC manages retains and releases for you. To be able to ensure that a methods exists, the method must be found in your project. While working with id the compiler cannot find any symbols. By restricting the protocol to NSObject ARC knows exactly that any possible delegate will contain "respondsToSelector". This ensures consistency and your memory management will be always fine. Classes which aren't matching NSObject will cause an error if used as delegate. – JackPearse Feb 24 '12 at 12:46
  • 1
    @piobyz: Because `respondsToSelector:` is part of the NSObject protocol. The `delegate` property is declared as `id `, which says only that the delegate responds to messages declared in that protocol. Thus, you need that protocol to conform to the NSObject protocol for the compiler to know that `respondsToSelector:` is among them. – Peter Hosey Apr 26 '12 at 15:14
  • 1
    @David: Not quite. `delegate` isn't declared with a class name, so the NSObject class is not relevant here—the compiler doesn't, and still doesn't, know that those two things are related. The “NSObject” that is part of the solution is the NSObject *protocol*, because that's where `respondsToSelector:` is declared. http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/ – Peter Hosey Apr 26 '12 at 15:17
  • @PeterHosey thanks for the heads-up. So I guess it's always a good idea to conform my custom protocol to at least protocol, the same as when subclassing NSObject? – Piotr Byzia Apr 26 '12 at 18:50
  • @piobyz: Yeah. There's not really any reason not to, and it lets you use most NSObject things (everything declared in the protocol) without making the compiler suspicious. – Peter Hosey Apr 26 '12 at 20:54
5

For Swift this becomes:

@objc protocol MTScrollViewDelegate: NSObjectProtocol

The NSObject protocol groups methods that are fundamental to all Objective-C objects.

For more information on what NSObjectProtocol is: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/index.html

niket
  • 141
  • 2
  • 4