我希望(在运行时)将参数绑定到函数,就像在boost :: bind中一样 - 有点像下面这样:
-(void)myFuncWithParameter:(NSString*)param {
NSLog(param);
}
-(void)init {
UIButton *helloButton = [UIButton buttonWithType:UIButtonTypeCustom];
[helloButton addTarget:self action:@selector(myFuncWithParameter:@"hello") forControlEvents:UIControlEventTouchUpInside];
}
所以...我正在动态地(在运行时)将值@“hello”绑定到参数。
显然上面的语法不正确。有谁知道这是否可能以及正确的语法?
干杯, 尼克。
答案 0 :(得分:3)
简短的回答是否定的,或者至少不是那个等级。
长期的答案是,在技术上可以构建类似于使用NSInvocations(和/或forwardInvocation:
)的东西,在methodForSelector中做一些聪明的事情:或者通过动态注册方法实现,但它非常棘手,特别是如果你关心速度的话。
如果我有一些代码来构建像这样的curried方法真的值得,我会做的就是这样(写在这个评论中,未经测试);
//FIXME: In a real implementation you would do some mangling, this code will get confused if you have _s in the curried selector, and thus could be exploitable
//This method makes a unique selector by mangling the arguments
- (SEL) selectorForSelector:(SEL)bindSel withString:(NSString *)bindString {
NSString *mangle = [NSString *stringWithFormat:@"LGBind_%@_%@"], NSStringFromSelector(bindSel), bindString];
SEL retval = NSSelectorFromString(mangle);
//Register the imp. You probably want to check if it is already reg
if (![self respondsToSelector:retval]) {
class_addMethod([self class], retval, LGBind_IMP, "v@:")l
}
}
//Generic dispatcher imp
void LGBind_IMP(id self, SEL _cmd) {
NSString *selectorName = NSStringFromSelector(_cmd);
NSArray *array [selectorName componentsSeparatedByString:@"_"];
//Skip index 0; it is @"LGBind"
NSString *originalSelectorString = [array objectAtIndex:1];
NSString *originalArgString = [array objectAtIndex:2];
//Get our the SEL and the IMP
SEL originalSEL = NSSelectorFromString(originalSelectorString);
IMP originalIMP = [self methodForSelector:originalSEL];
//call the original imp
originalIMP([self class], originalSEL, originalArgString);
}
显然,根据你的确切需要,你可以用不同的方式做某些事情,例如你可以懒洋洋地使用forwardInvocation中的imps,或者在实例的dict中隐藏有关管理选择器的数据,而不是仅将其管理到选择器名称中。
答案 1 :(得分:1)
一般的答案是目标 - 行动机制只允许目标,发送者和接收发送者的消息;因此,如果您需要访问数据,则必须从目标或发件人处获取数据。
一种选择是创建一个表示参数值,方法和对象的绑定的类。这个类有一个动作来调用对象上的方法,传递值。使用此类的实例作为目标。这是一个简单的例子:
@interface UnaryBinder : NSObject {
id target;
SEL selector;
id parameter;
}
@property id target;
@property SEL selector;
@property (retain) id parameter;
-(id)initWithTarget:(id)anObject selector:(SEL)aSelector param:(id)aParameter;
-(void)action:(id)sender;
@end
@implementation UnaryBinder
...
-(void)action:(id)sender {
[target performSelector:selector withObject:parameter];
}
@end
如果要支持任意数量的参数,则需要使用NSInvocation(如路易所提到的)而不是performSelector:withObject
。当然,控件不会保留其目标,因此您需要一些方法来保持UnaryBinder。此时,您可以跳过特殊类,只是将数据存储在控件中,正如您在使用KVP的评论中提到的那样。或者,将操作分解为控制器类,并使用该实例作为目标。在目标行动方面,UnaryBinder及其同类并没有真正提供任何优势。对于相关主题,谷歌“高阶消息”。