Передача данных через NSTimer UserInfo - PullRequest
27 голосов
/ 16 апреля 2010

Я пытаюсь передать данные через 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 ]

49 голосов
/ 16 апреля 2010

Вы должны правильно перенести информацию в словарь:

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

Поскольку таймер является повторяющимся таймером, вам больше не нужен словарь, поэтому вы можете его разблокировать.

7 голосов
/ 16 апреля 2010

Ваш звонок правильный, но вам не нужно приводить словарь к идентификатору. Вы можете получить userInfo со следующей строкой в ​​вашем notifyPause1: метод:

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

    NSDictionary *dict = [timer userInfo];

}
6 голосов
/ 25 января 2012

Вы можете запросить таймер в методе, указанном для селектора,

Затем вы можете получить 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 голосов
/ 30 марта 2013

Метод 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];

  }
2 голосов
/ 16 апреля 2010

sound и selector не являются объектами Objective-C: sound - это число без знака, а selector - указатель на структуру C. Это может вызвать какой-то сбой.

Вы хотите использовать NSValue для хранения значения для selector и NSNumber для хранения значения для sound. NSValue и NSNumber являются объектами и будут работать с NSMutableDictionary.

0 голосов
/ 16 апреля 2010

Вы не должны приводить свои объекты к идентификатору при назначении в словарь. Любой объект, который может быть встроен непосредственно в NSDictionary, уже получен из NSObject и неявно принимается за преобразование в id. Сохраните имя селектора как NSString (используя NSStringFromSelector()), а затем преобразуйте его обратно в селектор, используя NSSelectorFromString()

Клаус

...