#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». Спасибо, что указали на это.