У меня недавно была эта проблема, и оказалось , это была ошибка в Visual Studio Express 2013 . Мне пришлось удалить исходный файл из проекта и повторно добавить его, чтобы устранить ошибку.
Попытки попробовать, если вы считаете, что это может быть ошибка в компиляторе / IDE:
Эти два метода делают разные вещи. Если у вас есть таймер (вы его сохранили, назначили или скопировали), вам следует его освободить. Если вы запланировали его в цикле выполнения, вы должны сделать его недействительным, чтобы цикл выполнения освободил его. Если вы сделали и то, и другое, то вы должны разблокировать и аннулировать таймер (однако обычно достаточно иметь цикл выполнения, владеющий таймером).
Всегда, выпуск - это последнее, что вы делаете.Когда вы что-то выпускаете, нет гарантии, что разыменовать объект безопасно, а это значит, что отправлять ему ЛЮБОЕ сообщение больше не безопасно.
[сброс таймера]
необходимо вызывать только в том случае, если вы «владеете» таймером. Из документации Apple:
Поскольку цикл выполнения поддерживает таймер, с точки зрения управления памятью обычно нет необходимости сохранять ссылку на таймер после того, как вы его запланировали. Поскольку таймер передается в качестве аргумента, когда вы указываете его метод в качестве селектора, вы можете аннулировать повторяющийся таймер, когда это необходимо в этом методе. Однако во многих ситуациях вам также может понадобиться возможность аннулировать таймер - возможно, даже до его запуска. В этом случае вам нужно сохранить ссылку на таймер, чтобы вы могли отправить ему сообщение о недействительности, когда это необходимо. Если вы создаете незапланированный таймер (см. «Незапланированные таймеры» ), тогда вы должны поддерживать надежную ссылку на таймер (в среде с подсчетом ссылок вы сохраняете его), чтобы он не освобождался перед его использованием.
Что это значит?
Если вы alloc
и init
таймер, вы также должны освободить
его, например:
NSTimer * timer = [[NSTimer alloc] initWith...];
NSRunLoop * runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[timer release];
...
...
[timer invalidate];
timer = nil;
После того, как таймер был добавлен в цикл выполнения, нет причин для сохранения ссылки на него больше нет, так как он принадлежит циклам выполнения. В этом случае, как показано, вы должны освободить
таймер, как только добавите его в цикл выполнения, а затем просто аннулировать
, когда закончите. Последняя строка (установка таймера на nil
) предназначена для безопасности. Вызов invalidate
приведет к освобождению таймера (циклом выполнения), поэтому сохранять ссылку, указывающую на него, небезопасно. Установка локальной ссылки на nil
сохраняет кошерность.
Если, однако, вы создаете таймер, используя один из удобных методов, например:
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval ...];
Вам не нужно звоните [сброс таймера]
вообще! Удобный метод добавляет таймер в цикл выполнения, который затем владеет им, поэтому вам не нужно выполнять какое-либо управление памятью для возвращенного объекта таймера. Вы бы просто аннулировали
таймер, когда больше не хотите его использовать:
[timer invalidate];
timer = nil;
Или, если таймер не был настроен на повторение, вы бы вообще ничего не делали, так как он будет выпущен после его первое обращение.
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval ...];
Вам не вообще нужно вызывать [сброс таймера]
! Удобный метод добавляет таймер в цикл выполнения, который затем владеет им, поэтому вам не нужно выполнять какое-либо управление памятью для возвращенного объекта таймера. Вы бы просто аннулировали
таймер, когда больше не хотите его использовать:
[timer invalidate];
timer = nil;
Или, если таймер не был настроен на повторение, вы бы вообще ничего не делали, так как он будет выпущен после его первое обращение.
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval ...];
Вам не вообще нужно вызывать [сброс таймера]
! Удобный метод добавляет таймер в цикл выполнения, который затем владеет им, поэтому вам не нужно выполнять какое-либо управление памятью для возвращенного объекта таймера. Вы просто аннулируете
таймер, когда больше не хотите его использовать:
[timer invalidate];
timer = nil;
Или, если таймер не был настроен на повторение, вы бы вообще ничего не делали, так как он будет выпущен после его первое обращение.
Это правильный способ освободить таймер, который все еще может быть запущенным (и вы хотите остановиться).