Passing Data through NSTimer UserInfo

后端 未结 6 1877
抹茶落季
抹茶落季 2021-01-31 09:18

I am trying to pass data through userInfo for an NSTimer call. What is the best way to do this? I am trying to use an NSDictionary, this is simple enough when I have Objective-C

相关标签:
6条回答
  • 2021-01-31 09:58

    You should not cast your objects to id when assigning to the dictionary. Any object that can be embedded directly into a NSDictionary already derives from NSObject and are implicitly concidered cast to id. Store the name of the selector as an NSString (using NSStringFromSelector()) and then convert it back to a selector using NSSelectorFromString()

    Claus

    0 讨论(0)
  • 2021-01-31 10:00

    Your call is right, but you don't have to cast the dictionary to id. You can get the userInfo back with the following line in your notifyPause1: method:

    - (void)notifyPause1:(NSTimer *)timer {
    
        NSDictionary *dict = [timer userInfo];
    
    }
    
    0 讨论(0)
  • 2021-01-31 10:02

    You may ask for the timer in the method given to the selector,

    Then you can grab useInfo from that timer (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
    }
    
    0 讨论(0)
  • 2021-01-31 10:05

    sound and selector aren't Objective-C objects: sound is an unsigned number and selector is a pointer to a C struct . That's likely to cause a crash of some sort.

    You'll want to use NSValue to hold the value for selector and NSNumber to hold the value for sound. NSValue and NSNumber are objects and will work with the NSMutableDictionary.

    0 讨论(0)
  • 2021-01-31 10:06

    Laurent Etiemble's method works well for making good use of timer methods in subclasses of UIViewcontroller which can be easily used in a number of different view controllers.

    Below is a way to write a generic score display which can be used over and over in the same app by passing the view through NSTimer userInfo.

    .h (subclass of 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];
    
                }
    

    In the view controller

    .m

      - (void)viewDidLoad
      {
           [super viewDidLoad];
    
           //load ScoreDisplay
           [self timeRun:self.scoreDisplay];
    
      }
    
    0 讨论(0)
  • 2021-01-31 10:11

    You have to wrap the information correctly into the dictionary:

    - (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];
    
    }
    

    In notifyPause1:, you retrieve everything:

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

    As the timer is a repeating timer, you do not need the dictionary anymore, so you can release it.

    0 讨论(0)
提交回复
热议问题