Невозможно использовать RespondsToSelector с помощью ARC на Mac

83

Когда я звоню respondsToSelectorв среду ARC, я получаю следующее сообщение об ошибкеAutomatic Reference Counting Issue No known instance method for selector respondsToSelector:

Это заголовок

#import <AppKit/AppKit.h>


@class MTScrollView;

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


@interface MTScrollView : NSScrollView 
{

}

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

@end

Это файл реализации

#import "MTScrollView.h"

@implementation MTScrollView

@synthesize delegate;


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

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

@end

Любые предложения о том, почему я получаю эту ошибку?

Дэвид
источник

Ответы:

277

Сделайте протокол совместимым с NSObject

@protocol MTScrollViewDelegate <NSObject>

В противном случае компилятор не думает, что объект ответит на сообщения NSObject вроде respondsToSelector, и выдаст предупреждение. В любом случае он будет успешным во время выполнения без проблем.

Джейсон Харвиг
источник
2
@piobyz respondsToSelector- это метод экземпляра, NSObjectпоэтому системе необходимо знать, что делегат является одним из подклассовNSObject
Дэвид
1
@David, спасибо, вы правы, кроме того, вот еще немного информации: stackoverflow.com/questions/1304176/…
Петр Бизия
2
@piobyz в «старом мире» до ARC компилятор предполагал, что вы знаете, что делаете, и просто игнорировал некоторые вещи во время компиляции. Теперь ARC управляет сохранением и выпуском файлов для вас. Чтобы иметь возможность гарантировать, что метод существует, метод должен быть найден в вашем проекте. При работе с id компилятор не может найти никаких символов. Ограничивая протокол до NSObject, ARC точно знает, что любой возможный делегат будет содержать responsedsToSelector. Это гарантирует согласованность, и ваше управление памятью всегда будет в порядке. Классы, которые не соответствуют NSObject, вызовут ошибку, если используются в качестве делегата.
JackPearse
1
@piobyz: Потому что respondsToSelector:это часть протокола NSObject. delegateСвойство объявляется id <MTScrollViewDelegate>, что говорит лишь о том , что делегат отвечает на сообщения , объявленные в этом протоколе. Таким образом, вам нужно, чтобы этот протокол соответствовал протоколу NSObject, чтобы компилятор знал, что respondsToSelector:он среди них.
Питер Хози
1
@ Дэвид: Не совсем. delegateне объявлен с именем класса, поэтому класс NSObject здесь не имеет значения - компилятор не знает и до сих пор не знает, что эти две вещи связаны. «NSObject», который является частью решения, - это протокол NSObject , потому что он там respondsToSelector:объявлен. developer.apple.com/library/mac/documentation/Cocoa/Reference/…
Питер Хози,
4

Для Swift это становится:

@objc protocol MTScrollViewDelegate: NSObjectProtocol

Протокол NSObject группирует методы, которые являются фундаментальными для всех объектов Objective-C.

Для получения дополнительной информации о том, что такое NSObjectProtocol: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/index.html

никет
источник