Проблема с памятью при вызове dispatch_async с локальной переменной

У меня возникают проблемы в коде при вызове dispatch_async. Я думаю, что эта проблема связана с тем, что ARC восстанавливает объект до того, как он будет использован в блоке, поскольку метод, который его отправляет, завершает работу.

- (void) method:(SomeClass *) someClass {
  // local variable
  NSNumber *someValue = someClass.somePropertyOnManagedObject;
  dispatch_async(queue, ^() {
    /* call some singleton object passing variable 
     * when access the variable, reference is nil
     */
    [[DashboardFacade sharedInstance] someMethod:someValue];
  });
}

Просмотрев много документации, я заключаю

  • Блокировать доступ без параметров – нечего обсуждать
  • Block обращается к параметрам простого типа, например. BOOL, int — эти копируются и не проблема
  • Блокирует доступ к параметру метода, который его отправил - я не уверен, но думаю, что это нормально
  • Блокировать доступ к свойству self — до тех пор, пока self «живет», пока вызов не завершится нормально
  • Block accesses local variable in method that dispatched it
    • If we use some semaphores such that we wait for the block to return before leaving the method, then all ok
    • В противном случае переменная может быть удалена сборщиком мусора до того, как блок сможет быть использован.

Я думаю, что решение состоит в том, чтобы использовать модификатор __block, чтобы ARC сохранял переменную.

мой вопрос

  • Является ли вышеизложенное технически правильным, например. использование __block решит проблему, а не создаст другие проблемы?
  • Почему я не могу найти это нигде в Интернете / Google?

person chrisderham    schedule 17.01.2014    source источник
comment
блоки сохраняют параметры, которые вы им передаете. Поскольку в блоке используется someValue, на него сохраняется сильная ссылка. Я не думаю, что это ваша конкретная проблема.   -  person Abizern    schedule 17.01.2014
comment
__block просто делает переменную изменяемой внутри блока   -  person Mike Pollard    schedule 17.01.2014


Ответы (2)


Является ли вышеизложенное технически правильным, например. использование __block решит проблему, а не создаст другие проблемы?

Да, это технически правильно, __block в ARC позволяет вам изменить переменную (в данном случае туда, куда она указывает, поскольку это NSNumber *), которая была объявлена ​​вне контекста блока.

Почему я не могу найти это нигде в Интернете / Google?

Я думаю, что проблема связана не с этим конкретным местом вашего кода, а с чем-то другим.

person Rui Peres    schedule 17.01.2014

someValue внутри блока может быть нулевым, только если он равен нулю после этого присваивания:

NSNumber *someValue = someClass.somePropertyOnManagedObject;

Блоки сохраняют объекты, которые захватываются блоками в результате использования этих переменных внутри блоков. И неважно, self это или локальная переменная из области видимости, которая видна блоку.

person eofster    schedule 17.01.2014