NSBlockOperation и объекты в блоке

#ios #nsoperation #nsblockoperation

#iOS #nsoperation #nsblockoperation

Вопрос:

Вот простой код:

 // let's assume that I have to allocate this variable with alloc/init
NSString *someString = [[NSString alloc] initWithFormat:"%@", @"someString"];

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
}];

[queue addOperation:op]

[someString release];
  

Этот код приведет к сбою при запуске nsblockoperation с момента выпуска someString.
Каков наилучший способ предотвратить это?

Спасибо.

РЕДАКТИРОВАТЬ: ARC — это не выбор, поскольку это не мое решение. Есть ли способ обойти это в MRC?

EDIT2: как насчет следующего кода? Будет ли это работать?

 // let's assume that I have to allocate this variable with alloc/init
NSString *someString = [[NSString alloc] initWithFormat:"%@", @"someString"];

[someString retain]
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
  [someString release]
}];

[queue addOperation:op]

[someString release];
  

Комментарии:

1. ПОЧЕМУ, черт возьми, вы не используете ARC?

2. Если это не ваше решение, тогда возьмите молоток и ударьте человека, который хочет использовать MMR, по голове так сильно, как только сможете.

3. Спасибо за предложение. К сожалению, это тоже не вариант. Любые другие варианты??

4. Можно отключить / включить ARC на уровне файла. Возможно, в этом случае используйте ARC. Это избавит вас от головной боли. Тем не менее, здесь у вас есть потенциальная утечка, если операция никогда не выполняется (например: отменяется). Кроме того, нет необходимости добавлять дополнительное сохранение после его выделения — просто опустите это и release (после addOperation). Однако нет простого способа исправить случай освобождения строки, если операция будет отменена. Вероятно, вам лучше всего создать свой собственный класс NSOperation, который сохраняет строку и освобождает ее при освобождении операции.

Ответ №1:

 // let's say the variable is allocated with alloc/init
NSString *someString = [[[NSString alloc] initWithFormat:"%@", @"someString"] autorelease];

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
}];

[queue addOperation:op];
  

Существуют сотни тысяч приложений, которые нуждаются в обслуживании и не используют ARC. Оберните строку в авторелиз. Я думаю, что это должно сработать, но я не тестировал.

Ответ №2:

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

 // let's say the variable is allocated with alloc/init
NSString *someString = @"someString";

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
}];

[queue addOperation:op]
  

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

 // let's assume that I have to allocate this variable with alloc/init
NSString *someString = [[NSString alloc] initWithFormat:"%@", @"someString"];

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction: someString];
  [someString release]
}];

[queue addOperation:op]
  

Я знаю, что это просто пример кода, но если бы это было не так, вы также могли бы это сделать … 😉

 NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
  [someClass someFunction:@"someString"];
}];

[queue addOperation:op]
  

Комментарии:

1. Спасибо за ваше предложение. Однако ARC не является выбором для меня. Есть какие-либо обходные пути с MRC? Я также отредактировал свой OP. Извините, что не упомянул об этом.

2. @user3776727 хм, может быть, если вы предоставите какой-нибудь реальный код? В опубликованном вами коде вы можете просто someString заменить @"someString" и полностью удалить переменную за someString пределами блока, включая -release .

3. @user3776727 кроме того, [[NSString alloc] initWithFormat:"%@", "someString"] произойдет сбой, потому что вы пропускаете a @ перед "someString" (я сомневаюсь, что «some» переводится как правильный 32-разрядный isa указатель …)

4. Я тоже не могу этого сделать. Я не могу изменить 2 вещи из кода, который я опубликовал. 1. ARC -> MRC 2. использование alloc / init при создании переменной. Учитывая это, я думаю, нет способа обойти это??

5. Я исправил свою операцию по поводу @»someString». Спасибо, что указали на это.