我正在尝试通过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];
}
答案 0 :(得分:49)
您必须将信息正确地包装到字典中:
- (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...
}
由于计时器是一个重复计时器,你不再需要字典,所以你可以释放它。
答案 1 :(得分:7)
您的通话是正确的,但您不必将字典转换为ID。您可以使用notifyPause1:method中的以下行返回userInfo:
- (void)notifyPause1:(NSTimer *)timer {
NSDictionary *dict = [timer userInfo];
}
答案 2 :(得分:6)
您可以在给予选择器的方法中要求计时器,
然后你可以从该计时器中获取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
}
答案 3 :(得分:2)
sound
和selector
不是Objective-C对象:sound
是无符号数,selector
是指向C结构的指针。这可能会导致某种崩溃。
您需要使用NSValue来保存selector
和NSNumber的值来保存sound
的值。 NSValue和NSNumber是对象,可以使用NSMutableDictionary。
答案 4 :(得分:2)
Laurent Etiemble的方法适用于在UIViewcontroller的子类中充分利用计时器方法,可以很容易地在许多不同的视图控制器中使用。
下面是一种编写通用分数显示的方法,可以通过将视图传递给NSTimer userInfo在同一个应用中反复使用。
.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];
}
答案 5 :(得分:0)
分配到字典时,不应将对象转换为id。任何可以直接嵌入到NSDictionary
中的对象都已经从NSObject
派生而来,并且被隐式地强制转换为id。
将选择器的名称存储为NSString
(使用NSStringFromSelector()
),然后使用NSSelectorFromString()
将其转换回选择器
克劳斯