如何在Objective-C中构建类方法的NSArray(或NSMutableArray)?

jih*_*onc 14 objective-c

我正在尝试在Objective-C中构建一个NSArray方法.

(我在这里要完成的是C中的以下内容)

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

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

static const handler handler_table[10] = {
    handleCommandA, handleCommandB, handleCommandC
};
Run Code Online (Sandbox Code Playgroud)

我必须将它移植到Objective-C,我不知道如何在编译时构建一个函数指针数组(在Objective-c世界,类方法中).

在Objective-C中,我有以下内容.

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

/* Now how to add above 2 functions into NSArray? */
NSArray *handler_table = [NSArray arrayWithObjects:... ];  /* This doesn't seem to work. */
Run Code Online (Sandbox Code Playgroud)

And*_*ant 29

这里的问题是,要绑定这些函数,您必须使用返回SEL类型的selector关键字.这是指针类型,而NSArray存储对象.

你有三个选择;

  1. 使用常规的C型数组
  2. 将函数折叠到一个将调用它们的NSObject派生类中.
  3. 使用协议.

第二个可能更好,为此您可以使用NSValue类来保存选择器结果.例如;

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

NSArray *handler_table = [NSArray arrayWithObjects:selCommandA, selCommandB, nil ];
Run Code Online (Sandbox Code Playgroud)

当您从阵列中检索到正确的条目时,要转换回来,您会这样做;

SEL mySelector = [selCommand pointerValue];
[someObject performSelector:mySelector];
Run Code Online (Sandbox Code Playgroud)

(注意我假设你的objective-c语法中的这些用作对象的方法,而不是全局函数.如果你想在全局使用它们,那么你应该像在C中那样编写它们.)

另一种选择是将命令方法形式化为协议.这允许您编写可以在任何实现该协议的对象上工作的功能,并且编译器将提供比您只是调用选择器更多的检查.

例如

// 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
}
Run Code Online (Sandbox Code Playgroud)

然后编写处理和调度代码以使用"CommandHandler"类型的对象.例如

-(void) registerForCommands:(CommandHandler*)handler
Run Code Online (Sandbox Code Playgroud)


ter*_*kis 6

使用NSValue.

例如:

NSArray* handlers = [NSArray arrayWithObjects:[NSValue valueWithPointer:handleA] ... ];
Run Code Online (Sandbox Code Playgroud)

然后访问:

handleptr* handle = (handlerptr*)[[handlers objectAtIndex:0] pointerValue];
handle(foo_bar);
Run Code Online (Sandbox Code Playgroud)