0

在我的项目中,我有这样的功能:

- (void)doSomething:(NSError**)error {
...
}

我需要使用函数performSelector:onThread:withObject:waitUntilDone:在另一个线程上调用此函数,如下所示:

[self performSelector:@selector(doSomething:) onThread:anotherThread withObject:??? waitUntilDone:NO];

但是函数参数的类型是NSError**. 我正在考虑重构函数的参数类型,-(void)doSomething:并将NSError**类型NSValue*作为NSValue*参数传递。

这意味着,我需要将&error(类型为NSError **)包装成 aNSValue并将其作为参数传递,然后再将其解包。如何NSError**NSValue类包装和解包?

4

2 回答 2

0

我认为您可以使用NSValue'svalueWithPointer:pointerValue. 但我建议您使用其他东西,例如 GCD 来异步运行块,而不是更改方法的签名以适应以下限制performSelector

dispatch_async(anotherQueue, ^{
    [self doSomething:&error];
});

如果你真的想走这条路,这个问题还有一些关于如何解决这个问题的想法。

于 2016-08-12T21:34:53.480 回答
0

您需要重新考虑解决此问题的方法。你的方法:

- (void)doSomething:(NSError**)error

遵循传递变量地址的标准 Objective-C 模式,NSError *以便方法可以设置变量以返回错误。

如果您尝试异步调用此方法,无论performSelector:onThread:withObject:waitUntilDone:是尝试还是使用 GCD(正如 Felipe Cypriano 也建议的那样),您必须小心 - 您传递的地址的变量必须在执行异步调用时存在,即使你已经解决了你必须弄清楚异步调用何时完成,这样你才能检查它是否设置了变量......

处理此类问题的一种常见方法是使用完成块,异步方法在完成时调用它,传递任何结果 -NSError *在您的情况下。例如,您可以编写一个方法:

- (void) doSomethingAsyncAndThen:(void (^)(NSError *))completionBlock
{
   dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0),
                  ^{
                     NSError *error = nil;
                     [self doSomething:&error];
                     completionBlock(error);
                  });
}

并称之为:

[self doSomethingAsyncAndThen:^(NSError *error) { NSLog(@"error: %@", error); }];

尽管您将想做的不仅仅是NSLog结果。

高温高压

于 2016-08-12T23:20:06.130 回答