【问题标题】:ObjC: cast of an indirect pointer to an Objective-C pointerObjC:将间接指针转换为 Objective-C 指针
【发布时间】:2011-12-13 14:50:13
【问题描述】:

如何更改以下代码以与 ARC 兼容:

MyObj* fn = nil;
[self performSelectorOnMainThread:@selector(popSomething:) withObject:(id)&fn waitUntilDone:YES];

现在,我收到以下错误:

error: cast of an indirect pointer to an Objective-C pointer to '__strong id' is disallowed with ARC [4]

【问题讨论】:

  • 你为什么不能用[self performSelectorOnMainThread:@selector(queuedFileNamesPop:) withObject:fn waitUntilDone:YES];来代替?
  • @AndreyZ:因为那样,在这个调用返回之后,fn 仍然是nil
  • @Albert:那是因为 fn 最初是 nil
  • @MusiGenesis:是的,通过传递&fn,被调用的函数实际上可以覆盖它(这就是我想要的)。

标签: objective-c automatic-ref-counting


【解决方案1】:

如果您希望主线程更新字符串,那么更好的方法是使用可变字符串并将其简单地传递给主线程:

NSMutableString* fn = [NSMutableString string];
[self performSelectorOnMainThread:@selector(queuedFileNamesPop:) withObject:fn waitUntilDone:YES];

那么主线程就可以简单的更新字符串了。

【讨论】:

  • 为什么那会是更好的方法?有没有办法以某种方式将对象从被调用函数(queuedFileNamesPop)传递给被调用者?此解决方案现在适用于NSString。如果我想传递一些没有可用可变类的其他对象怎么办?
  • performSelectorOnMainThread 没有为您提供返回对象的任何选项,因此您必须传入一个放置返回值的位置。另一种选择是传递一个 NSMutableArray 并让被调用者将它想要的任何内容放入数组中。
  • 是的,我想过使用NSMutableArray 之类的东西。但我不确定,这对我来说太像黑客了。这是常见的方法吗?
  • (顺便说一句,我更新了我的问题。我真的不希望这个问题具体到 NSString。)
【解决方案2】:

参数的类型应该是(id *),即。指向对象的指针,而不是对象。

但如果你只想从需要在主线程上执行的方法中返回一个值,更好的解决方案是使用块和 GCD:

__block id poppedFilename;
dispatch_sync(dispatch_get_main_queue(), ^{
     poppedFilename = [self popFilename];
});
// do something with the popped file

这会在主线程上执行-popFilename 方法,并将结果存储在poppedFilename 中。您必须注意不要在主线程上调用此方法,因为它会死锁。如果你不确定你是否在主线程上,你可以使用这样的东西:

__block id poppedFilename;
if ([NSThread isMainThread]) {
     poppedFilename = [self popFilename];
} else {
     dispatch_sync(dispatch_get_main_queue(), ^{
         poppedFilename = [self popFilename];
     });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-10
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多