Подтвердить что ты не робот

Передача данных через NSTimer UserInfo

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

Ответ 1

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

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

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

Ответ 2

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

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

    NSDictionary *dict = [timer userInfo];

}

Ответ 3

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

Затем вы можете захватить 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
}

Ответ 4

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

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

Ответ 5

Метод Laurent Etiemble хорошо работает для эффективного использования методов таймера в подклассах UIViewcontroller, которые могут быть легко использованы в нескольких разных контроллерах представлений.

Ниже приведен способ записи общего индикатора результатов, который можно использовать снова и снова в одном приложении, передавая представление через пользовательскую информацию NSTimer.

.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];

  }

Ответ 6

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

Клаус