- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在将一段代码迁移到自动引用计数 (ARC),并让 ARC 迁移器抛出错误
NSInvocation's setArgument is not safe to be used with an object with ownership other than __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 迁移器说使用强保持指针作为 NSInvocation 的 -setArgument:
的参数是不安全的,除非您使用 __unsafe_unretained
的东西?
最佳答案
这完全是猜测,但这可能与通过引用作为 void*
传递的参数有关吗?
在您提到的情况下,这似乎并不是真正的问题,但如果您要打电话,例如。 getArgument:atIndex:
那么编译器将无法知道是否需要保留返回的参数。
来自 NSInvocation.h:
- (void)getArgument:(void *)argumentLocation atIndex:(NSInteger)idx;
- (void)setArgument:(void *)argumentLocation atIndex:(NSInteger)idx;
鉴于编译器不知道该方法是否会通过引用返回(这两个方法声明具有相同的类型和属性),也许迁移者(明智地)谨慎并告诉您避免指向 strong 的 void 指针指针?
例如:
NSDecimalNumber* val;
[anInvocation getArgument:&val atIndex:2];
anInvocation = nil;
NSLog(@"%@", val); // kaboom!
__unsafe_unretained NSDecimalNumber* tempVal;
[anInvocation getArgument:&tempVal atIndex:2];
NSDecimalNumber* val = tempVal;
anInvocation = nil;
NSLog(@"%@", val); // fine
关于objective-c - 为什么 ARC 迁移器说 NSInvocation 的 -setArgument : is not safe unless the argument is __unsafe_unretained?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8672675/
我正在使用 NSInvocation 调用一个我在编译时不知道的方法。 它工作正常,因为我没有找到如何传递 NSError** 类型的参数。 举个例子,假设我想从 NSFileManager 调用方法
以下代码抛出异常。 vcClass 是一个 Class 对象(继承自 UIViewController)。 Self 包含 我的实现 viewWillAppear: SEL viewWillAppea
既然可以直接调用方法,为什么还要使用 NSInvocation?需要问这个问题是因为我无法理解需要使用这个类。与仅调用如下方法相比,使用它有什么优势。 [myArray addObject:mySt
这个问题在这里已经有了答案: NSInvocation getReturnValue: called inside forwardInvocation: makes the returned obj
我想在未来安排一个函数调用。我正在使用 Swift。 我想回调一个私有(private)方法并返回一个 Promise(来自 PromiseKit) 我见过的所有例子都用到了 NSTimer.sche
什么是NSInspiration?何时以及如何使用它? 最佳答案 NSInvocation是消息发送的具体化。换句话说,它是一个代表消息发送的对象。 假设您的 Foo 类有一个名为 -[Foo foo
我创建了一个弱目标定时器类,当目标被释放时,定时器不会触发并自动失效。代码是这样的: //ViewController.m @interface TestObj : NSObject @end @im
有谁知道如何将 NSInvocation 的参数设置为 nil ?我正在尝试使用 OCMock,我希望这种期望返回 nil。问题是调用该方法时我需要做一些其他事情,正如您在示例中看到的那样,这就是为什
我有一个方法,它采用类似这样的可变参数,参数以 nil 结尾。 -(void)manyParams:(NSString *)st, ... { va_list argList; va_
我想使用一个将指向 NSError 对象的指针作为参数的方法来创建一个 NSInvocation 对象。这方面的一个例子是方法 - - (BOOL)writeToFile:(NSString *)pa
下面是我从Apple的“Timer Programming Topics”看到的示例代码: NSMethodSignature *methodSignature = [self methodSigna
我如何(或什至可以)将 nil 参数传递给 NSInvocation 对象? 我试着这样做: NSMethodSignature* signature = [AClass instanceMethod
我正在尝试在 Swift 中创建一个可重用的测试工具,子类将扩展测试工具以提供被测实例,并且可以添加它们自己的特定于子类的测试方法,如下所示: class FooTestHarness: XCTest
NSInvocation 究竟是如何工作的?有好的介绍吗? 我在理解以下代码(来自 Cocoa Programming for Mac OS X,第 3 版)的工作原理方面特别有问题,但我也能够独立于
我使用运行时特性向类中添加了一个类方法,但是NSInvocation 无法使用该方法。我的代码是这样的: id metaClass = object_getClass((id)protocolClas
我对 NSInvocation 有一个奇怪的问题。当网络操作完成时,我将它用作返回回调。让我更详细地解释一下前面的句子: 我正在使用通过 TCP 套接字工作的定制网络协议(protocol),并且我有
我认为我犯了一个根本性的错误,但我一生都看不到它。 我正在从 C++ 类(已锁定)中调用 Objective-C 对象的方法。我正在使用 NSInvocation 来防止我不得不编写数百个方法来访问这
我们有以下方法,适用于对象。它接受一个对象的方法并将结果放在 returnValueContainer 中: + (void)invokePrivateMethod:(SEL)selector ret
我收到这条消息: “(null):无法识别的选择器发送到类 0x3f52e824” 我试过的基本代码: SEL sel = @selector(applyProperties:toObject:);
我试图将 block 参数传递给 NSInvocation,但应用程序崩溃了。调用发出网络请求并调用成功或失败 block 。我认为问题在于 block 在网络请求完成之前被释放。我设法让它与一些 B
我是一名优秀的程序员,十分优秀!