2010-04-16 69 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]; 

    }