NSTimer возможная причина сбоя - PullRequest
1 голос
/ 24 февраля 2012

У меня проблема при работе с NSTimer. Давайте предположим, что у меня есть эта архитектура:

ThreadedClass.m (содержит таймер NSTimer *;)

- (id) init {
  if (self = [super init]) {
    // do blablabla
    [self launchAThread];
  }
  return self;
}


- (void) launchAThread {
    [NSThread detachNewThreadSelector:@selector(selectorToMyThreadFunction)
                             toTarget:self
                           withObject:nil];
}


- (void) selectorToMyThreadFunction {
    //I do my stuff in here
    //Then i relaunch a Timer to call this function
    //periodically but it has to be "atomic" so no
    //repeating timer since i don't know the time
    //this function will take

    //I do some [self changeSomething];

    [self restartTimer];

    //MyThread ends here (and might be recreated by the Timer's bip
}

- (void)restartTimer {
    if (![NSThread isMainThread]) {
      [self performSelectorOnMainThread:@selector(restartTimer)
                             withObject:nil
                          waitUntilDone:NO];
      return;
    }

    [timer invalidate];
    [timer release];
    timer = [[NSTimer scheduledTimerWithTimeInterval:interval
                                              target:self
                                            selector:@selector(launchWithTimer:)
                                            userInfo:nil
                                             repeats:NO] retain];
}

- (void) launchWithTimer:(NSTimer *)theTimer {
  if (theTimer == timer)
  {
    [timer release];
    timer = nil;
    [self launchAThread];
  }
  else
  {
    //Nothing to be done in here, a user launch a thread manually
  }
}

Итак, давайте предположим, что пользователь класса выделил его и выпустил сразу после него. Мой таймер все еще будет жив и объект тоже (так как таймер выполняет сохранение). Когда таймер сработает, он будет делать [self launchAThread], а затем таймер будет признан недействительным и освободит себя. И он освободит мой объект, который теперь имеет retainCount = 0 ... Предположим, еще раз, что объект освобожден сразу после это приведет к краху, и я ничего не могу сделать, чтобы остановить это, что приходит мне в голову.

Я согласен, это много предположений, но мне интересно знать, если у кого-то уже была эта проблема и как он ее решил.

Спасибо за чтение, и я надеюсь, что я был ясен! :)

Ответы [ 5 ]

1 голос
/ 24 февраля 2012

Вы должны всегда делать недействительным свой таймер, прежде чем отпустить его.Если таймер является частью контроллера представления, я всегда делаю его недействительным в viewWillDisappear.Для меня это так странно, что NSTimers сохраняет своих владельцев.Я думаю, что лучший способ - создать - (void) метод cleanUp, который сделает недействительным таймер и предупредит пользователя класса, чтобы ВСЕГДА использовать cleanUp перед выпускомЕсли кто-нибудь знает лучший способ, я буду рад.

0 голосов
/ 04 апреля 2012

Сначала я тоже прибег к использованию функции очистки.У меня также есть объект A, владеющий объектом B, который содержит таймер - который сохраняет объект B. Когда объект A освобождается, он освобождает объект B, но B живет, потому что таймер сохранил его.Затем в методе, запущенном, но по таймеру, я использую отношение делегата для обратного вызова объекта A → аварийное завершение работы.Вот где объект A должен «очистить» таймер B.Это может привести к другим проблемам, хотя, если другие объекты также полагаются на объект B. А также класс A не должен и не может знать секреты реализации класса B. отношения перед выпуском осуществляются в деаллоке А, потому что вы не знаете, умрет ли Б, даже если вы его отпустили - кто-то другой мог его сохранить (НРАВИТСЯ, ЧТО D *** NSTIMER) ...: -P

0 голосов
/ 20 марта 2012

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

Поэтому, чтобы решить мою проблему, я добавил новый «слой»: новый класс, которыйсделаю часть потока и таймера, так что я являюсь пользователем этого класса, и я знаю, что должен очистить!

0 голосов
/ 25 февраля 2012

NSRunloop сохранит таймер для вас, а это значит, что вам вообще не нужно сохранять / отпускать его

0 голосов
/ 25 февраля 2012

Если вы не используете повторяющийся таймер, почему бы не использовать dispatch_after?Вы избавите себя от головной боли и издержек объекта NSTimer.И если вы просто придерживаетесь GCD, вы также можете избежать вызова на detachNewThreadSelector:.

...