Должен ли я когда-нибудь звонить dispatch_release в ARC?

(Но этот вопрос совершенно другой)

Этот пример кода, отличного от ARC, устанавливает таймер на основе GCD и вызывает dispatch_release для объекта dispatch_source_t:

    __block BOOL done = NO;
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    if (timer) {
        uint64_t milliseconds = 100ull;
        uint64_t interval = milliseconds * NSEC_PER_MSEC;
        uint64_t leeway = 10ull * NSEC_PER_MSEC;
        __block typeof(self) _self = self;

        dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
        dispatch_source_set_event_handler(timer, ^{
            //[_progressBar setProgress:exportSession.progress animated:YES];
            if (done) {
                dispatch_source_cancel(timer);
                dispatch_release(timer);
                _self.exportingMovieLabel.hidden = YES;
                _self.exportingProgress.hidden = YES;
            }
        });

        dispatch_resume(timer);
    }

Я узнал, что вам не нужно выделять объекты очереди в ARC. Но другие объекты GCD, такие как источник отправки?

Ответ 1

Нет, если целью развертывания является iOS 6.0 или Mac OS X 10.8 или новее, как описано здесь.

Все объекты GCD управляются ARC, поэтому вам не нужно явно управлять своей памятью. То, что верно для dispatch_queue_t, также относится ко всем другим объектам GCD.

Это описано в <os/object.h> прямо над определением OS_OBJECT_HAVE_OBJC_SUPPORT.

По умолчанию объекты libSystem, такие как объекты GCD и XPC, объявляются как Objective-C типы при создании с помощью компилятора Objective-C. Это позволяет им участвовать в ARC, управлении RR с помощью среды исполнения Blocks и проверять утечки с помощью статического анализатора и позволяет добавлять их в коллекцию Cocoa.

Вы также можете отказаться от этого поведения, используя флаг -DOS_OBJECT_USE_OBJC=0 компилятора.

Ответ 2

Ниже приведена директива компилятора для добавления в ваш код.

// If GCD objects are treated as Objective C object then we do not need to call dispatch_release on those GCD object.
// Checking if OS_OBJECT_HAVE_OBJC_SUPPORT == 0 ensures we are only releasing GCD objects when they are NOT being treated as Objective C objects.
#if OS_OBJECT_HAVE_OBJC_SUPPORT == 0
    dispatch_release(timer);
#endif