Подтвердить что ты не робот

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

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

id <MyProtocol> variable;

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

id <MyProtocol, MyOtherProtocol> variable;

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

4b9b3361

Ответ 1

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

id <MyProtocol, MyOtherProtocol> variable;

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

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

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

Ответ 2

Да, этот синтаксис верен.

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

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

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

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

#import <objc/runtime.h>

Protocol * p = objc_getProtocol("MyProtocol");
if (class_conformsToProtocol([myObj class], p)) {
  //conformance!
}

Ответ 3

Вы не всегда проверяете соответствие протокола во время компиляции, потому что объект (неквалифицированный) тип 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;