Я переносил блок кода в автоматический подсчет ссылок (ARC), и мигратор ARC выдавал ошибку
NSInvocation setArgument небезопасно для использования с объектом с
право собственности, кроме __unsafe_unretained
в коде, где я выделил объект, используя что-то вроде
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:@"1.0"];
затем установите его в качестве аргумента NSInvocation, используя
[theInvocation setArgument:&testNumber1 atIndex:2];
Почему это мешает вам сделать это? Кажется столь же плохим использовать __unsafe_unretained
объекты в качестве аргументов. Например, следующий код вызывает сбой в 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_unretained
tempNumber
не удерживает его после того, как исходный указатель установлен на nil
(имитирует случай, когда вызов используется после исходного ссылка на аргумент ушла). Если строка -retainArguments
не закомментирована (в результате чего NSInvocation удерживает аргумент), этот код не вылетает.
Точно такой же сбой происходит, если я использую testNumber1
непосредственно в качестве аргумента -setArgument:
, и это также исправляется, если вы используете -retainArguments
. Почему же тогда ARC-переносчик говорит, что использование строго удерживаемого указателя в качестве аргумента для -setArgument:
NSInvocation небезопасно, если вы не используете что-то, что __unsafe_unretained
?