使用PresentModalViewController更改视图时出现EXC_BAD_ACCESS错误

时间:2011-12-08 22:18:20

标签: ios cocoa-touch uikit exc-bad-access

我正在尝试使用这段代码在我的应用中切换视图:

self->variable1 = [[NSNumber alloc] initWithInt:0];
self->variable2 = [[NSMutableArray arrayWithCapacity:1];
self->variable3 = [[NSMutableArray arrayWithCapacity:1];

[self presentModalViewController:titleScreen animated:YES];

如果我注释掉所有分配的变量行,代码工作正常。如果代码中只有1行崩溃,则出现“EXC_BAD_ACCESS”错误。为什么会这样?变量根本没有被使用,只是声明供以后使用。我也没有得到任何编译错误。我做错了什么?

更新
谢谢大家的帮助。我改变了将我的变量声明为@ property / @ synth以清理我的代码的方式,但它没有解决问题。经过长时间的摆弄,我修好了。我改变了代码:

self.variable1 = [[NSNumber alloc] initWithInt:0];

到此:

self.variable1 = [NSNumber alloc];
[self.variable1 initWithInt:0];

它有效!有人可以解释为什么这有效,第一行没有?

更新

谢谢Peter Hosey向我展示了我的邪恶方式。这次我很确定它是固定的。我正在将变量Releases存储在

-(void)release

我没有意识到xCode会在需要时发布。我将所有变量版本移动到

-(void)Destroy

所以我可以释放MY命令中的所有内容。现在代码有效了。再次感谢!

3 个答案:

答案 0 :(得分:1)

variable2variable3在您提交模态视图之后实际访问它们(大概)之前会被自动释放。

至少将行改为:

self->variable2 = [[NSMutableArray arrayWithCapacity:1] retain];
self->variable3 = [[NSMutableArray arrayWithCapacity:1] retain];

self->variable2 = [[NSMutableArray alloc] initWithCapacity:1];
self->variable3 = [[NSMutableArray alloc] initWithCapacity:1];

variable1应该没问题。

最好使用@property@synthesize,这样您就可以使用点表示法:

<强>·H

@interface MyClass : SuperClass

@property (nonatomic,retain) NSMutableArray *variable2;
@property (nonatomic,retain) NSMutableArray *variable3;

@end

<强>的.m

@implementation MyClass
@synthesize variable2,varible3;

- (void)foo {

    self.variable2 = [NSMutableArray arrayWithCapacity:1];
    self.variable3 = [NSMutableArray arrayWithCapacity:1];

}

@end

答案 1 :(得分:1)

我建议您将variable1variable2variable3声明为属性,而不是实例变量。然后,使用self.variable1self.variable2self.variable3来访问它们。

点语法(self.variable1等)使用您在每个属性上声明的内存管理策略;箭头语法(self->variable1等)将直接访问变量。崩溃是因为您在远处创建了两个不会让您拥有它们的数组,然后没有将数组分配给保留它们的属性。

您可能还希望升级项目以使用ARC。然后没有内存管理差异;分配给实例变量而不是属性不会导致对象过早释放,因为ARC默认将实例变量视为所有权。您可能仍希望在切换到ARC后切换到使用属性,但不是为了防止崩溃。


回复您的修改:

  

我改变了将变量声明为@ property / @ synth以清理代码的方式,但它没有解决问题。

然后别的错了。

你从未对问题本身说过太多。你说你有一个EXC_BAD_ACCESS,但没有什么声明引发了崩溃,或者你将它归咎于你所展示的代码的理由。

  

我改变了代码:

self.variable1 = [[NSNumber alloc] initWithInt:0];

但这是正确的代码。这就是你应该使用的东西。

  

到此:

self.variable1 = [NSNumber alloc];
[self.variable1 initWithInt:0];

不要!该代码在多个层面上是错误的,错误的,错误的。

init方法(包括initWithWhatever:方法)不保证返回您发送邮件的同一对象。 NSNumber的initWithInt:很可能

该对象创建一个未初始化的 NSNumber对象,并将其分配给该属性。然后它将initWithInt:发送给该对象,该对象将返回一个初始化对象,可以和很可能是一个不同的对象 。现在你拿着一个未初始化的对象(你稍后会尝试使用它)并将初始化的对象放在地板上。

永远不会在单独的表达式中发送allocinitWith…)。始终使用相同的表达式发送它们。没有例外。否则,您冒着保留未初始化对象而不是初始化对象的风险。在您的情况下(使用NSNumbers),几乎可以肯定会发生什么。

您应该做的是声明和合成拥有NSNumber对象的强属性,并在单个语句中创建NSNumber对象:[[NSNumber alloc] initWithInt:][NSNumber numberWithInt:]。如果您不使用ARC,则需要后者,因为该属性将保留该对象。如果您使用ARC,它们实际上是等效的。

如果你的代码崩溃,那么其他东西是错误的,所以请在这个问题或新问题中告诉我们 - 关于崩溃,以便我们可以帮助你找到它的真正原因。

答案 2 :(得分:0)

默认情况下,objective-c中的所有实例变量都具有受保护的范围。因此,除非您在接口文件中明确声明它们为:

@interface MYClass {

@public
    NSNumber *variable1;
    NSMutableArray *variable2;
    NSMutableArray *variable3;
}
//...
@end

然后使用struct dereferencing运算符无法访问它们。这可能是导致EXC_BAD_ACCESS错误的原因。