为Objective-C类声明私有成员变量的正确方法是什么?

时间:2011-02-06 07:50:28

标签: iphone objective-c variables

我无法在以下初始化程序中使用变量赋值:

- (id)initWithBaseURL:(NSString *)url  {
  self = [super initWithNibName:@"MyNibName" bundle:nil];
  if (self) {
    baseURL = [url copy];
  }

  return self;
}

我已经验证了url参数对于适当的内容是有效的(创建为通过NSXMLParser构建的NSMutableString,然后在调试器中的initWithBaseURL方法中检查),但是在将复制操作的结果分配给baseURL之后,baseURL变量“超出范围”并仍然无效。在类的其他方法中访问baseURL变量的任何尝试都会导致EXC_BAD_ACCESS错误。

我已经在.h文件中声明了baseURL,如下所示,没有@property或@synthesize操作,因为我试图将它用作私有成员变量:

@interface SignInViewController : UIViewController {
  // other variables

  @private
  NSString *baseURL;
}

// Other @property delcarations, IBAction method declartions, and method declarations

@end

我还尝试使用here描述的技术,但这只会导致初始化程序中出现EXC_BAD_ACCESS错误。

我在做什么会导致EXC_BAD_ACCESS错误发生,我该如何解决?

2 个答案:

答案 0 :(得分:4)

以下是一些可能相关或不相关的观察结果。

  • 从Obj-C的角度来看,您发布的代码绝对可以。
  • 您应该真正调用UIViewController的指定初始值设定项[super init]而不是initWithNibName:bundle:
  • 您将方法命名为initWithBaseURL:,但它将NSString作为参数。虽然这与@interface中的声明匹配,但请确保您不希望baseURL成为代码中其他位置的NSURL对象。
  • 删除@private后会发生什么?我怀疑你看到的例外没有任何变化。

请确保不要这样做:

NSString *myURL = [NSString stringWithFormat:...]; // myURL is autoreleased
SignInViewController *controller = [[SignInViewController alloc] initWithBaseURL: myURL]; // retains myURL because it's immutable
[myURL release]; // does not crash because myURL has been *retained*
// baseURL is left with 0 retain count

您可以验证向NSMutableString发送copy确实产生了另一个对象,而向不可变NSString发送copy等同于retain,只是因为在不可变的精确副本上浪费内存对象效率低下。如果baseURL确实是myURL的副本,则会在自动释放池耗尽时发生崩溃。

换句话说,错误可能在一个地方,只在另一个地方表现出来。上面的例子并不算太多。

答案 1 :(得分:3)

你已经正确地宣布了它。此外,您发布的程序是正确的。

:CORR:

正如Costique捕获的那样:你应该通过一个超类的指定初始化器来调用。