2010-04-16 64 views
27

我想通过userInfo传递数据进行NSTimer调用。做这个的最好方式是什么?我想使用NSDictionary,当我有Objective-C对象时,这很简单,但其他数据呢?我想要做这样的事情,不作为就是工作:通过NSTimer传递数据UserInfo

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

当你进入'-notifyPause1:'时'cb' nil: – 2010-04-16 09:34:48

回答

7

您的来电是对的,但你没有投的字典ID。你可以得到的用户信息,同时显示以下线在notifyPause1:方法:

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

    NSDictionary *dict = [timer userInfo]; 

} 
2

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

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

0

分配给字典时,不应将对象转换为标识。任何可以直接嵌入到NSDictionary中的对象都已经从NSObject派生出来,并被隐式地强制转换为id。 商店选择为名称的NSString(使用NSStringFromSelector()),然后将其转换回使用NSSelectorFromString()

克劳斯

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

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

+0

抬头 - 如果您确实为您的NSTimer调用* invalidate *,请确保在访问* userInfo *之前检查* isValid *标志。这是在* userInfo *属性的文档中陈述的,我刚在这个确切的地方发生了崩溃。 – NAlexN 2017-10-11 17:04:26

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 
} 
2

洛朗埃蒂安布勒的方法效果很好用于在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]; 

    }