答案 0 :(得分:2)
答案 1 :(得分:1)
答案 2 :(得分:0)
正如其他几个答案所指出的那样,NSTimer签名是
- (void)methodName:(NSTimer *)timer;
如果你需要有时直接调用一个方法,有时通过一个计时器(或者可能是包含你需要的参数的字典的字典),而不是包装,你可能要考虑添加一组辅助宏来放置在你的项目.pch文件
#define ifThenElse(_if_,_then_,_else_) ( (_if_) ? _then_ : _else_ )
#define isClass(objectToTest,isOfClass) ifThenElse(objectToTest==nil,NO,[objectToTest isKindOfClass:[isOfClass class]])
#define asClass(object,requiredClass) \
/**/ifThenElse(isClass(object,requiredClass),\
/*****/((requiredClass *)object),\
/****/nil\
/***/)
#define asClassViaMethod(object,requiredClass,viaClass,viaMethod) \
/**/ifThenElse(isClass(object,requiredClass),\
/*****/(requiredClass *)object,\
/*****/ifThenElse(isClass(object,viaClass),\
/*********/(requiredClass *)[(viaClass*)object viaMethod],\
/*********/nil)\
/***/)
你使用它们的方式相对简单,并且imho使代码更容易读取,而不是将函数包装3次以考虑变体调用。
但首先是一些关于它是如何工作的背景信息。
你的计时器方法选择器可以用它最基本的形式表达,
- (void)myMethod:(id)sender;
途中没有任何令人讨厌的事情发生。这意味着“发送者”没有任何对象类型,并且你不能用它做很多事情,而不会将它转换为你期望的类型。 然而,在你可以安全地施放之前,你需要确定该对象的类型是正确的。
这些宏的帮助在于它们用一系列测试来包装发送者,这些测试过滤掉不正确的类型并返回nil,而不是允许你向不能响应它的对象发送错误的选择器。请注意,宏本身可以用更简洁的方式表达,但是为了理解它们是如何工作的,并且没有任何性能开销,我选择用注释来表达它们。你可以随时削减它们,但是没有真正的性能优势,因为它们会产生相同的编译输出。
理论用例:
NSTimer收件人 - 您希望NSNumber可以使用,但计时器会自行发送给您。
- (void)myMethod:(id)sender{
NSNumber *argument = asClassViaMethod(sender,NSNumber,NSTimer,userInfo);
}
UIGestureRecognizer收件人 - 您希望视图与之合作,由GR发送给您自己。
- (void)myMethod:(id)sender{
NSNumber *argument = asClassViaMethod(sender,UIView,UIGestureRecognizer,view);
}
您正在扩展的自定义方法,但不想破解它 它曾经是:
- (void)myMethod:(NSNumber *)number{
[myOtherObject setNumber:number];
}
但它现在需要一个NSNumber&一个NSString,而不仅仅是一个NSNumber。你有时也可能只想发送一个NSString
调整后的方法标题和参数解析器
- (void)myMethod:(id)sender{
NSNumber *number = asClassViaMethod(sender,UIView,NSDictionary,objectForKey:@"number");
NSNumber *string = asClassViaMethod(sender,UIView,NSDictionary,objectForKey:@"string");
if (number) {
// do something funky with number
}
if (string) {
// do something funky with string
}
}
现实世界使用示例剪切和粘贴我的一个项目:
NSInteger artistIndex = asClassViaMethod(artistIndex_, NSNumber, NSTimer, userInfo).integerValue;
...
NSDictionary *payload = asClassViaMethod(sender,NSDictionary,NSTimer,userInfo);
作为旁注,这是一种向计时器方法发送多个参数的便捷方式,当你想要直接调用该方法的灵活性时,没有包装器......
UIView *tappee = asClassViaMethod(sender,UIView,UITapGestureRecognizer,view);
...
for (id element in connectArray) {
NSURL *url = asClassViaMethod(element, NSURL, NSDictionary, objectForKey:@"url");
NSArray *additionalHeaders = asClassViaMethod(element, NSArray, NSDictionary, objectForKey:@"headers");
NSString *path = [url path];
NSString *query = [url query];
if (query.length) {
path = [[url path] stringByAppendingFormat:@"?%@",query];
}
[self requestDocument:path additionalHeaders:additionalHeaders];
}
在最后一个示例中,如果数组包含NSURL,则使用该值,并将“additionalHeaders”解析为nil。 如果数组包含一个包含NSURL的NSDictionary和一个分别带有@“url”和@“headers”键的NSArray,它将使用提供的值。
最后,如果不明显,请调用您的计时器方法
[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(myMethod:) userInfo:[NSNumber numberWithInteger:myNSInteger] repeats:NO];
......或......
[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(myMethod:) userInfo:[NSDictionary dictionaryWithObjectsAndKeys: myNSNumber,@"number",myNSString,@"string",nil] repeats:NO];