Я переносил блок кода на автоматический подсчет ссылок (ARC), и мигратор ARC выдал ошибку
NSInvocation's setArgument небезопасно использовать с объектом с право собственности, отличное от __unsafe_unrehibited
в коде, где я выделил объект, используя что-то вроде
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:@"1.0"];
, а затем установил его как аргумент NSInvocation, используя
[theInvocation setArgument:&testNumber1 atIndex:2];
Почему это мешает вам сделать это? Кажется столь же плохим использовать объекты __ unsafe_unrehibited
в качестве аргументов.Например, следующий код вызывает сбой в ARC:
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:@"1.0"];
NSMutableArray *testArray = [[NSMutableArray alloc] init];
__unsafe_unretained NSDecimalNumber *tempNumber = testNumber1;
NSLog(@"Array count before invocation: %ld", [testArray count]);
// [testArray addObject:testNumber1];
SEL theSelector = @selector(addObject:);
NSMethodSignature *sig = [testArray methodSignatureForSelector:theSelector];
NSInvocation *theInvocation = [NSInvocation invocationWithMethodSignature:sig];
[theInvocation setTarget:testArray];
[theInvocation setSelector:theSelector];
[theInvocation setArgument:&tempNumber atIndex:2];
// [theInvocation retainArguments];
// Let's say we don't use this invocation until after the original pointer is gone
testNumber1 = nil;
[theInvocation invoke];
theInvocation = nil;
NSLog(@"Array count after invocation: %ld", [testArray count]);
testArray = nil;
из-за чрезмерного освобождения testNumber1
, потому что временная переменная __ unsafe_unrehibited
tempNumber
не сохраняет его после исходный указатель устанавливается на nil
(имитирует случай, когда вызов используется после того, как исходная ссылка на аргумент исчезла). Если строка -retainArguments
раскомментирована (в результате чего NSInvocation удерживает аргумент), этот код не аварийно завершается.
Тот же самый сбой происходит, если я использую testNumber1
непосредственно в качестве аргумента для -setArgument:
, и он также исправляется, если вы используете -retainArguments
. Почему же тогда мигратор ARC говорит, что использование строго удерживаемого указателя в качестве аргумента NSInvocation -setArgument:
небезопасно, если вы не используете что-то, что является __ unsafe_unreolated
?