Проверка соответствия объекта двум отдельным протоколам в Objective-C - PullRequest
13 голосов
/ 10 января 2011

В Objective-C, когда вы объявляете переменную экземпляра, вы можете проверить, соответствует ли она протоколу присваивания во время компиляции, вот так:

id <MyProtocol> variable;

Можно ли проверить, соответствует ли объект, назначенный переменной, двум отдельным протоколам во время компиляции? Как в:

id <MyProtocol, MyOtherProtocol> variable;

Я знаю, что могу выполнять проверку во время выполнения, используя conformsToProtocol: и respondsToSelector и др. (Что я делаю до фактического использования объекта для дополнительной безопасности), и я мог бы написать свой собственный метод установки, который выполняет проверку, но я хотел бы знать во время компиляции.

Ответы [ 3 ]

54 голосов
/ 10 января 2011

Да, этот синтаксис правильный.

Правильный способ проверить, соответствует ли объект протоколу:

if ([myObj conformsToProtocol:@protocol(MyProtocol)]) {
  //conformance!
}

Обратите внимание, что это работает как метод экземпляра и метод класса.

Если по какой-то странной причине вы не можете использовать conformsToProtocol:, вы можете перейти к уровню времени выполнения:

#import <objc/runtime.h>

Protocol * p = objc_getProtocol("MyProtocol");
if (class_conformsToProtocol([myObj class], p)) {
  //conformance!
}
13 голосов
/ 10 января 2011

Я думаю, что лучше всего использовать собственный код:

id <MyProtocol, MyOtherProtocol> variable;

И перед вызовом метода проверьте, отвечает ли переменная тому, что вы хотите вызвать:

if ([variable respondsToSelector:@selector(aMethod:)]) {
    [variable aMethod:nil];
}

Поскольку Objective-C является динамическим языком, простое объявление протокола переменной не может гарантировать его соответствие протоколу.В основном он генерирует предупреждения при сборке.

3 голосов
/ 10 января 2011

Вы не всегда можете проверить соответствие протокола во время компиляции, потому что объект (неквалифицированного) типа id всегда является допустимым объектом с точки зрения компилятора.Например,

id<P1> p1;
id<P2> p2;
id p0;

// compiler warning: assigning to 'id<P1>' from incompatible type 'id<P2>'
p1 = p2;

// no compiler warning
p0 = p2;
p1 = p0;

При этом <P1, P2> выдаст вам предупреждения в случае, если объект не соответствует обоим протоколам , если , что может быть известно во время компиляции:

id<P1> p1;
id<P2> p2;
id<P1, P2> p12;
id<P1, P2> q12;
id p0;

p12 = p1; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P1>'
p12 = p2; // warning: assigning to 'id<P1,P2>' from incompatible type 'id<P2>'
p12 = q12; // no compiler warning

// no compiler warning
p0 = p1;
p12 = p0;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...