30

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

6 回答 6

52

您必须将信息正确包装到字典中:

- (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...
}

由于计时器是一个重复计时器,您不再需要字典,因此您可以释放它。

于 2010-04-16T15:45:53.603 回答
7

您的电话是正确的,但您不必将字典转换为 id。您可以在 notifyPause1: 方法中使用以下行获取 userInfo:

- (void)notifyPause1:(NSTimer *)timer {

    NSDictionary *dict = [timer userInfo];

}
于 2010-04-16T09:38:12.873 回答
6

您可以在提供给选择器的方法中要求计时器,

然后您可以从该计时器(timer.userInfo)中获取 useInfo :

- (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
}
于 2012-01-25T14:12:28.070 回答
2

sound并且selector不是 Objective-C 对象:sound是一个无符号数并且selector是一个指向 C 结构体的指针。这可能会导致某种崩溃。

您需要使用 NSValue 来保存 for 的值,selector并使用 NSNumber 来保存 的值sound。NSValue 和 NSNumber 是对象,将与 NSMutableDictionary 一起使用。

于 2010-04-16T10:02:43.223 回答
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];

  }
于 2013-03-30T11:14:40.690 回答
0

分配给字典时,不应将对象强制转换为 id。任何可以直接嵌入到 a 中的对象都NSDictionary派生自NSObject并隐含地转换为 id。将选择器的名称存储为NSString(使用NSStringFromSelector()),然后使用将其转换回选择器NSSelectorFromString()

克劳斯

于 2010-04-16T10:05:58.503 回答