在Objective-C中实现调度表:如何声明选择器数组

时间:2021-10-25 22:53:53

I'm trying to implement a dispatch table, so that I can call a selector with the following example code:

我正在尝试实现一个调度表,这样我就可以用以下示例代码调用一个选择器:

NSInteger i = 2;
[myObject performSelector:selectors[i]];

I'm trying to store user preferences which affect which method of an API gets called. Right now, I use the string name of the selector and use NSSelectorFromString, but that's a bit messy. If I use a dispatch table, then I can store an enum instead.

我试图存储用户首选项,它会影响调用API的哪个方法。现在,我使用选择器的字符串名和NSSelectorFromString,但这有点混乱。如果我使用一个调度表,那么我可以存储一个enum。

How can I make an array of selectors, or a dispatch table in Objective-C?

如何在Objective-C中创建选择器数组或分派表?

Edit:

编辑:

The compiler complains when I try to set an array of selectors as a property. @property SEL[] won't compile.

当我试图将选择器数组设置为属性时,编译器会报错。@ property选取[]不会编译。

Edit2:

Edit2:

I'm using my KosherCocoa API library and I want to call a single method at once, based on a saved user setting. I'm saving to and reading from a Plist file.

我正在使用我的KosherCocoa API库,我想一次调用一个方法,基于保存的用户设置。我从一个Plist文件中保存并读取。

3 个解决方案

#1


3  

You can use the SEL type to hold selectors. Simply:

您可以使用SEL类型来保存选择器。简单:

SEL dispatchTable[3] = { @selector(doThis:), 
                         @selector(doThat:), 
                         @selector(doTheOther:) 
                       };

To your edit, use an NSArray/NSDictionary/etc of selectors as your property instead. You are not allowed to use C arrays as properties in Objective C; they are not one of the supported types (which are ObjC objects, CF types and basic C 'Plain Old Data' types.)

要进行编辑,请使用NSArray/NSDictionary/等选择器作为属性。在Objective C中不允许使用C数组作为属性;它们不是受支持的类型之一(它们是ObjC对象、CF类型和基本的C 'Plain Old Data'类型)。

OK, on our comments below, you need to wrap the selector in an NSValue to allow you to use it in an objc container (because SEL is a C pointer type):

好的,在下面的评论中,您需要将选择器封装到一个NSValue中,以便在objc容器中使用它(因为SEL是C指针类型):

NSMutableArray * dispatchTable2 = [[NSMutableArray alloc] initWithCapacity:3];
SEL selIn = @selector(doThis:);

// Wrap the selector in an NSValue instance
[dispatchTable2 addObject:[NSValue valueWithPointer:selIn]];

// On extracting:
NSValue * valOut = [dispatchTable2 objectAtIndex:0];
SEL selOut = [[dispatchTable2 objectAtIndex:0] pointerValue];
[anObject performSelector:selOut];

So now your table is an objc container stored as a property or ivar, and you use NSValue to wrap SEL pointers with valueWithPointer: and get the SEL out with pointerValue.

现在你的表是一个objc容器存储为属性或ivar,你使用NSValue用valueWithPointer:用pointerValue将SEL取出。

#2


2  

I would recommend using NSInvocation instead of selectors. They are far more flexible, as you can send the same invocation to many objects and you can change its properties as you go.

我建议使用NSInvocation而不是选择器。它们的灵活性要大得多,因为您可以向许多对象发送相同的调用,并且您可以在运行时更改其属性。

#3


1  

One way to do this is using an array of NSStrings, then converting those to SELs at runtime, if that increases readability for you..

一种方法是使用一个nsstring数组,然后在运行时将它们转换为SELs,如果这能提高可读性的话。

NSString *selectors[] = { ... } 

[myObject performSelector:NSSelectorFromString(selectors[i])];

To use this as a property, use

要将其用作属性,请使用

@property(nonatomic, assign) NSString **selectors;

#1


3  

You can use the SEL type to hold selectors. Simply:

您可以使用SEL类型来保存选择器。简单:

SEL dispatchTable[3] = { @selector(doThis:), 
                         @selector(doThat:), 
                         @selector(doTheOther:) 
                       };

To your edit, use an NSArray/NSDictionary/etc of selectors as your property instead. You are not allowed to use C arrays as properties in Objective C; they are not one of the supported types (which are ObjC objects, CF types and basic C 'Plain Old Data' types.)

要进行编辑,请使用NSArray/NSDictionary/等选择器作为属性。在Objective C中不允许使用C数组作为属性;它们不是受支持的类型之一(它们是ObjC对象、CF类型和基本的C 'Plain Old Data'类型)。

OK, on our comments below, you need to wrap the selector in an NSValue to allow you to use it in an objc container (because SEL is a C pointer type):

好的,在下面的评论中,您需要将选择器封装到一个NSValue中,以便在objc容器中使用它(因为SEL是C指针类型):

NSMutableArray * dispatchTable2 = [[NSMutableArray alloc] initWithCapacity:3];
SEL selIn = @selector(doThis:);

// Wrap the selector in an NSValue instance
[dispatchTable2 addObject:[NSValue valueWithPointer:selIn]];

// On extracting:
NSValue * valOut = [dispatchTable2 objectAtIndex:0];
SEL selOut = [[dispatchTable2 objectAtIndex:0] pointerValue];
[anObject performSelector:selOut];

So now your table is an objc container stored as a property or ivar, and you use NSValue to wrap SEL pointers with valueWithPointer: and get the SEL out with pointerValue.

现在你的表是一个objc容器存储为属性或ivar,你使用NSValue用valueWithPointer:用pointerValue将SEL取出。

#2


2  

I would recommend using NSInvocation instead of selectors. They are far more flexible, as you can send the same invocation to many objects and you can change its properties as you go.

我建议使用NSInvocation而不是选择器。它们的灵活性要大得多,因为您可以向许多对象发送相同的调用,并且您可以在运行时更改其属性。

#3


1  

One way to do this is using an array of NSStrings, then converting those to SELs at runtime, if that increases readability for you..

一种方法是使用一个nsstring数组,然后在运行时将它们转换为SELs,如果这能提高可读性的话。

NSString *selectors[] = { ... } 

[myObject performSelector:NSSelectorFromString(selectors[i])];

To use this as a property, use

要将其用作属性,请使用

@property(nonatomic, assign) NSString **selectors;