在块中使用ivar返回到其他对象

Ada*_*ach 2 iphone objective-c objective-c-blocks

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

调试器给了我很多东西,它停止了

 UIViewController *result = [self factory](self);
Run Code Online (Sandbox Code Playgroud)

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

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

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

这适用于调试版本,但在ad hoc中崩溃...

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

这既适用于调试也适用于ad hoc,但非常难看和冗余:

- (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];
  }
}
Run Code Online (Sandbox Code Playgroud)

我的理论是boolValue在返回的块执行时变得不可访问.它是

@interface SubclassOfNSObjectInheritor : NSObjectInheritor
{
  BOOL boolValue;
}

@property (readonly) BOOL boolValue;
Run Code Online (Sandbox Code Playgroud)

(YES或者NO在SubclassOfNSObjectInheritor的init中分配)和

@synthesize boolValue;
Run Code Online (Sandbox Code Playgroud)

在SubclassOfNSObjectInheritor的实现中.

最后的问题是 - 我的理论是错误的吗?这是第三种方式 - 在ad hoc和调试版本中工作 - 安全吗?做这个的最好方式是什么?

Jas*_*oco 6

你的问题是双重的,首先是你过度释放你的块,然后在堆栈上创建块,当你的方法返回时它就会消失(你基本上是将指针返回到先前被破坏的堆栈帧).

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

您在各种配置中崩溃是纯粹的偶然事件.所以,要修复你的一个实现:

- (FactoryMethod) factory;
{
  return [[^(NSObjectInheritor *newThing)
  {
    if(boolValue)
    {
      return [[ViewControllerClass alloc] initWithStuff:foo];
    }
    else
    {
      return [[ViewControllerClass alloc] initWithStuff:bar];
    }
  } copy] autorelease];
}
Run Code Online (Sandbox Code Playgroud)