, как указано в нескольких других ответах, сигнатура 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;
без каких-либо неприятных событий на пути.все это означает, что «отправитель» не имеет типа объекта, и вы не можете многое с ним сделать, не приведя его к типу, который вы ожидаете.прежде чем вы сможете безопасно выполнить приведение, вам необходимо точно знать, что объект имеет правильный тип.
Вот где макросы помогают в том, что они оборачивают отправителя серией тестов, отфильтровывающих неправильные типы иверните ноль вместо того, чтобы позволить вам отправить неправильный селектор объекту, который не может ответить на него.обратите внимание, что сами макросы могут быть выражены более кратко, однако для понимания того, как они работают, и без каких-либо потерь производительности, я решил выразить их с комментариями.Вы всегда можете их урезать, однако реального выигрыша в производительности нет, так как они приведут к тому же скомпилированному выводу.
примеры теоретического использования:
Получатель 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" разрешается в ноль.если массив содержит NSDictionary, содержащий NSURL и NSArray с ключами @ "url" и @ "headers" соответственно, он использует предоставленные значения.
наконец, если это не очевидно, вызовВаш метод таймера
[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];