Vraag Hoe een NSArray (of NSMutableArray) van klassemethoden in Objective-C te bouwen?


Ik probeer een NSArray van methoden te bouwen in Doelstelling C.

(Wat ik hier probeer te bereiken, is zoiets als het volgende in C)

typedef (void)(*handler)(int command);

void handleCommandA(void) { ... }
void handleCommandB(void) { ... }

static const handler handler_table[10] = {
    handleCommandA, handleCommandB, handleCommandC
};

Ik moet dit naar Objective-C porten en ik weet niet hoe een scala aan functie-aanwijzers opbouwen (in de Objective-c wereld, klassemethoden) tijdens het compileren.

In Objective-C heb ik het volgende.

- (void)handleCommandA { ... }
- (void)handleCommandB { ... }

/* Now how to add above 2 functions into NSArray? */
NSArray *handler_table = [NSArray arrayWithObjects:... ];  /* This doesn't seem to work. */

14
2018-02-22 15:21


oorsprong


antwoorden:


Gebruik NSValue.

Bijvoorbeeld:

NSArray* handlers = [NSArray arrayWithObjects:[NSValue valueWithPointer:handleA] ... ];

dan om toegang te krijgen tot:

handleptr* handle = (handlerptr*)[[handlers objectAtIndex:0] pointerValue];
handle(foo_bar);

6
2018-04-30 15:54



Het probleem hier is dat om die functies te binden, u het selector-sleutelwoord moet gebruiken dat een SEL-type retourneert. Dit is een aanwijstype terwijl NSArray objecten opslaat.

Je hebt dus drie opties;

  1. Gebruik een gewone array van het C-type
  2. Vouw de functies samen in een NSObject-afgeleide klasse die ze zal oproepen.
  3. Gebruik een protocol.

De tweede is waarschijnlijk mooier en hiervoor kunt u de klasse NSValue gebruiken om de selectorresultaten vast te houden. bijv;

NSValue* selCommandA = [NSValue valueWithPointer:@selector(handleCommandA:)];
NSValue* selCommandB = [NSValue valueWithPointer:@selector(handleCommandB:)];

NSArray *handler_table = [NSArray arrayWithObjects:selCommandA, selCommandB, nil ];

Als je de juiste invoer uit de array hebt opgehaald, zou je om terug te converteren;

SEL mySelector = [selCommand pointerValue];
[someObject performSelector:mySelector];

(Opmerking: ik veronderstel dat vanuit uw objectief-c-syntaxis deze zijn bedoeld om te worden gebruikt als methoden voor een object en niet voor globale functies.Als u ze globaal wilt gebruiken, moet u ze op dezelfde manier schrijven als in gewone C.)

Een andere optie is om de opdrachtmethoden in een protocol te formaliseren. Hiermee kunt u functionaliteit schrijven die werkt op elk object dat dat protocol implementeert en de compiler zorgt voor meer controle dan wanneer u alleen selectors aanroept.

Bijv.

// some header
@protocol CommandHandler
@required
-(void) handleCommandA;
-(void) handleCommandB;
@end

// some other header
@interface someClass : NSObject<CommandHandler>
{
// you will receive compiler warnings if you do not implement the protocol functions
}

Uw verwerkings- en verzendcode wordt vervolgens geschreven om te werken met objecten van het type "CommandHandler". bijv

-(void) registerForCommands:(CommandHandler*)handler

29
2018-02-22 17:53



In Objective-C geef je geen methoden door; je gaat rond selectors, die in feite de canonieke namen van methoden zijn. Om een ​​object te laten reageren op een selectorbericht, verzendt u het vervolgens performSelector:. Bijvoorbeeld:

NSString *exampleString = [NSString stringWithString:@"Hello"];
SEL methodName = @selector(stringByAppendingString:);
  // ^This is the selector. Note that it just represents the name of a
  //  message, and doesn't specify any class or implementation
NSString *combinedString = [exampleString performSelector:methodName withObject:@" world!"];

Wat je wilt is een array van NSStrings maken met daarin de namen van de selectors waarin je geïnteresseerd bent. Je kunt de functie gebruiken NSStringFromSelector() om dit te doen. Bel dan als u ze wilt gebruiken NSSelectorFromString() op de snaren om de originele selector terug te krijgen en door te geven aan de juiste objecten performSelector:. (Zoals in het bovenstaande voorbeeld wordt getoond, is de ontvanger niet gecodeerd in een selector - alleen de naam van de methode - dus moet u de ontvanger mogelijk ook opslaan.)


4
2018-02-22 18:35