/ / Zgodność z listą protokołów - cel-c, cel-c-protokół

Zgodny z listą protokołów - cel-c, cel-c-protokół

Mam warunek, w którym chcę, aby kontroler widoku był zgodny z dowolnym z 4 protokołów.

Czy istnieje sposób, aby sprawdzić, czy jest on zgodny z którymkolwiek z tych 4 protokołów bez robienia kilku lub instrukcji w moim if?

Czy potrafisz stworzyć tablicę protokołów?

Odpowiedzi:

5 dla odpowiedzi № 1

Jasne, możesz stworzyć szereg protokołów:

NSArray *protocols = @[@protocol(UIApplicationDelegate),
@protocol(UIImagePickerControllerDelegate),
@protocol(UIScrollViewDelegate),
@protocol(NSFileManagerDelegate)];

Następnie możesz sprawdzić, czy jakiś obiekt jest zgodny z nimi wszystkimi:

UIViewController *vc = ...;
for (Protocol *protocol in protocols) {
if (![vc conformsToProtocol:protocol]) {
NSLog(@"object doesn"t conform to %@", protocol);
}
}

Trudno to sobie wyobrazić czemu jednak chciałbyś to zrobić w czasie wykonywania.

Być może tak naprawdę chcesz zadeklarować, że coś jest zgodne z kilkoma protokołami. Możesz to zrobić, a kompilator sprawdzi to za Ciebie podczas kompilacji. Na przykład:

@property (nonatomic, strong) id<UIApplicationDelegate, UIImagePickerController,
UIScrollViewDelegate, NSFileManagerDelegate> swissArmyKnife;

Jeśli spróbujesz przypisać coś do tej właściwości, która nie jest zgodna ze wszystkimi czterema protokołami, kompilator wygeneruje ostrzeżenie.

Być może mówisz, że chcesz sprawdzić, czy obiekt jest zgodny przynajmniej jeden z protokołów, ale nie musi on być zgodny z wszystkimi. W takim przypadku musisz sprawdzić w czasie wykonywania. Ale dla mnie to pachnie źle.

Jeśli chcesz wysłać wiadomość do obiektu, alenie jesteś pewien, czy zrozumie wiadomość, prawdopodobnie lepiej jest sprawdzić konkretnie wiadomość, którą chcesz wysłać, zamiast sprawdzać zgodność protokołu.

// This is probably not such a good idea.
if ([object conformsToProtocol:@protocol(NSFileManagerDelegate)]) {
return [object fileManager:myFileManager shouldRemoveItemAtURL:url];
} else {
return arc4random_uniform(2);
}


// This is probably better.
if ([object respondsToSelector:@selector(fileManager:shouldRemoveItemAtURL:)]) {
return [object fileManager:myFileManager shouldRemoveItemAtURL:url];
} else {
return arc4random_uniform(2);
}

1 dla odpowiedzi nr 2

Pewnie.

id object = ...;
Protocol *protocols[] = {@protocol(Blah), @protocol(Foo), @protocol(Bar)};
for(unsigned i = 0; i < sizeof(protocols) / sizeof(Protocol *); ++i) {
if([object conformsToProtocol:protocols[i]]) {
//do something...
break;
}
}