通过NSTimer UserInfo传递数据

时间:2010-04-16 09:31:00

标签: iphone objective-c nstimer

我正在尝试通过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];
}

6 个答案:

答案 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)

soundselector不是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()将其转换回选择器

克劳斯