Передача данных через NSTimer UserInfo
Я пытаюсь передать данные через userInfo для вызова NSTimer. Каков наилучший способ сделать это? Я пытаюсь использовать NSDictionary, это достаточно просто, когда у меня есть объекты Objective-C, но как насчет других данных? Я хочу сделать что-то вроде этого, которое не работает так:
- (void)play:(SystemSoundID)sound target:(id)target callbackSelector:(SEL)selector
{
NSLog(@"pause ipod");
[iPodController pause];
theSound = sound;
NSMutableDictionary *cb = [[NSMutableDictionary alloc] init];
[cb setObject:(id)&sound forKey:@"sound"];
[cb setObject:target forKey:@"target"];
[cb setObject:(id)&selector forKey:@"selector"];
[NSTimer scheduledTimerWithTimeInterval:0
target:self
selector:@selector(notifyPause1:)
userInfo:(id)cb
repeats:NO];
}
Ответы
Ответ 1
Вы должны правильно перевести информацию в словарь:
- (void) play:(SystemSoundID)sound target:(id)target callbackSelector:(SEL)selector
{
NSLog(@"pause ipod");
[iPodController pause];
theSound = sound;
NSMutableDictionary *cb = [[NSMutableDictionary alloc] init];
[cb setObject:[NSNumber numberWithInt:sound] forKey:@"sound"];
[cb setObject:target forKey:@"target"];
[cb setObject:NSStringFromSelector(selector) forKey:@"selector"];
[NSTimer scheduledTimerWithTimeInterval:0
target:self
selector:@selector(notifyPause1:)
userInfo:cb
repeats:NO];
[cb release];
}
В notifyPause1:
вы получаете все:
- (void)notifyPause1:(NSTimer *)timer {
NSDictionary *dict = [timer userInfo];
SystemSoundID sound = [[dict objectForKey:@"sound"] intValue];
id target = [dict objectForKey:@"target"];
SEL selector = NSSelectorFromString([dict objectForKey:@"selector"]);
// Do whatever...
}
Поскольку таймер является повторяющимся таймером, вам больше не нужен словарь, поэтому вы можете его освободить.
Ответ 2
Ваш звонок прав, но вам не нужно вводить словарь в id. Вы можете вернуть userInfo со следующей строкой в методе notifyPause1::
- (void)notifyPause1:(NSTimer *)timer {
NSDictionary *dict = [timer userInfo];
}
Ответ 3
Вы можете запросить таймер в методе, указанном в селекторе,
Затем вы можете захватить useInfo с этого таймера (timer.userInfo):
- (void)settingTimer
{
[NSTimer scheduledTimerWithTimeInterval:kYourTimeInterval
target:self
selector:@selector(timerFired:)
userInfo:yourObject
repeats:NO];
}
- (void)timerFired:(NSTimer*)theTimer
{
id yourObject = theTimer.userInfo;
//your code here
}
Ответ 4
sound
и selector
не являются объектами Objective-C: sound
- это беззнаковое число, а selector
- указатель на структуру C. Это может вызвать какой-то крах.
Вы хотите использовать NSValue для хранения значения для selector
и NSNumber для хранения значения для sound
. NSValue и NSNumber являются объектами и будут работать с NSMutableDictionary.
Ответ 5
Метод Laurent Etiemble хорошо работает для эффективного использования методов таймера в подклассах UIViewcontroller, которые могут быть легко использованы в нескольких разных контроллерах представлений.
Ниже приведен способ записи общего индикатора результатов, который можно использовать снова и снова в одном приложении, передавая представление через пользовательскую информацию NSTimer.
.h(подкласс UIViewcontroller)
- (NSTimeInterval) timeSet;
- (void) timeRun: (UISegmentedControl*)scoreDisplay;
- (void) timeWrite: (NSTimer *)timer;
.m
- (NSTimeInterval) timeSet {
return [self.startTime timeIntervalSinceNow];
}
- (void) timeWrite: (NSTimer *)timer
{
NSDictionary *dict = [timer userInfo];
UISegmentedControl *scoreDisplay = [dict objectForKey:@"scoreDisplay"];
int myint = round([self timeSet]);
NSString* buttonWrite = [[[NSString stringWithFormat:@"Score: %d", self.answered] stringByAppendingString:[NSString stringWithFormat:@" Errors: %d", self.errors]] stringByAppendingString:[NSString stringWithFormat:@" Time: %d", (myint*-1)]];
[scoreDisplay setTitle:buttonWrite forSegmentAtIndex:0];
}
- (void) timeRun: (UISegmentedControl*)scoreDisplay
{
self.startTime = [NSDate date];
NSMutableDictionary *cb = [[NSMutableDictionary alloc] init];
[cb setObject:scoreDisplay forKey:@"scoreDisplay"];
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(timeWrite:)
userInfo:cb
repeats:YES];
}
В контроллере представления
.m
- (void)viewDidLoad
{
[super viewDidLoad];
//load ScoreDisplay
[self timeRun:self.scoreDisplay];
}
Ответ 6
Вы не должны отбрасывать свои объекты на id при назначении словаря. Любой объект, который может быть встроен непосредственно в NSDictionary
, уже происходит от NSObject
и неявно рассматривается как cast to id.
Сохраните имя селектора как NSString
(используя NSStringFromSelector()
), а затем преобразуйте его обратно в селектор с помощью NSSelectorFromString()
Клаус