2

我在目标 iOS 4 的 iPhone 应用程序中发现了崩溃,该崩溃取决于构建类型。

调试器没有给我太多继续,它停在

 UIViewController *result = [self factory](self);

使用 EXC_BAD_ACCESS。self是一个继承自 NSObject 的类(如下所示为 NSObjectInheritor)。僵尸已启用。我尝试factory了三种方法更改方法,结果如下。

这在调试和临时构建中都会崩溃......

- (FactoryMethod) factory;
{
    return [^ UIViewController * (NSObjectInheritor *newThing)
    {
      return [[ViewControllerClass alloc] initWithStuff:(boolValue ? foo : bar)];
    } autorelease];
}

这在调试版本中有效,但在临时崩溃中...

- (FactoryMethod) factory;
{
  return [^ UIViewController * (NSObjectInheritor *newThing)
  {
    if(boolValue)
    {
      return [[ViewControllerClass alloc] initWithStuff:foo];
    }
    else
    {
      return [[ViewControllerClass alloc] initWithStuff:bar];
    }
  } autorelease];
}

这适用于调试和临时,但非常丑陋和冗余:

- (FactoryMethod) factory;
{
  if(boolValue)
  {
    return [^ UIViewController * (NSObjectInheritor *newThing)
    {
      return [[ViewControllerClass alloc] initWithStuff:foo];
    } autorelease];
  }
  else
  {
    return [^ UIViewController * (NSObjectInheritor *newThing)
    {
      return [[[ViewControllerClass alloc] initWithStuff:bar];
    } autorelease];
  }
}

我的理论是boolValue在执行返回的块时变得无法访问。这是

@interface SubclassOfNSObjectInheritor : NSObjectInheritor
{
  BOOL boolValue;
}

@property (readonly) BOOL boolValue;

YES或者NO当然是在 SubclassOfNSObjectInheritor 的 init 中分配)和

@synthesize boolValue;

在 SubclassOfNSObjectInheritor 的实现中。

最后的问题是——我关于错误的理论是否正确?第三种方式——即在临时和调试版本中工作——安全吗?做这个的最好方式是什么?

4

1 回答 1

6

你的问题是双重的,首先你过度释放你的块,其次,块是在堆栈上创建的,当你的方法返回时它会消失(你基本上是在返回一个指向先前销毁的堆栈帧的指针)。

相反,复制块并在返回之前自动释放它。您可以通过消息以objective-c方式执行此操作copy,您可以调用该Block_copy()函数。

您在各种配置中的崩溃纯属偶然。因此,要修复您的实现之一:

- (FactoryMethod) factory;
{
  return [[^(NSObjectInheritor *newThing)
  {
    if(boolValue)
    {
      return [[ViewControllerClass alloc] initWithStuff:foo];
    }
    else
    {
      return [[ViewControllerClass alloc] initWithStuff:bar];
    }
  } copy] autorelease];
}
于 2010-07-01T02:17:24.847 回答