【问题标题】:Problem with NSObject init methodNSObject 初始化方法的问题
【发布时间】:2010-01-03 09:18:07
【问题描述】:

我对标准 NSObject 的 init() 方法有疑问。我写了一个类(EFAPersistence),它是 NSObject 的子类。 EFAPersistance 有一个名为 efaDatabase 的属性。

EFAPersistence.h

@interface EFAPersistence : NSObject {
  FMDatabase * efaDatabase;
}

@property (assign) FMDatabase * efaDatabase;

每次创建 EFAPersistance 实例时,我都想从我的 AppDelegate 中为 efaDatabase 分配一个值。

EFAPersistence.m

@implementation EFAPersistence

@synthesize efaDatabase;

- (id)init {
  if (self = [super init]) {
    efaDatabase = [[NSApp delegate] efaDatabase];
  }
  return self;
}

@end

这种分配方式行不通。但是,如果我将代码放在正常的方法中,它就会起作用。所以我确信 efaDatabase 已在我的 AppDelegate 中正确实例化。它只是在我的 init() 方法中不起作用。这就是为什么我觉得 NSApp 在 init() 方法中不起作用的原因。

这就是重要的 AppDelegate 代码的样子。

AppDelegate.h

@interface AppDelegate : NSObject <NSApplicationDelegate> {
  FMDatabase * efaDatabase;
}

AppDelegate.m

- (id)init {
  if (self = [super init]) {
    NSString * databasePath = 
      [[NSBundle mainBundle] pathForResource:@"efa" ofType:@"sqlite"];

    self.efaDatabase = [FMDatabase databaseWithPath:databasePath];

    if (![efaDatabase open]) {
      NSLog(@"Couldn't open database: %@", databasePath);
      // TODO: Create a database here
    }
    self.db = [[EFAPersistence alloc] init];
  }
  return self;
}

如您所见,我正在调用 init 方法。我还通过使用 NSLog() 确认了这一点。 init() 被调用。我试图在 EFAPersistence 中分配的属性也是在调用 init() 之前创建的。

总结一下:

如何在 init() 方法中完成这项工作,这样我就不必在所有 EFAPersistence 方法中编写样板代码?

【问题讨论】:

  • 语法说明:在 Objective-C 中引用实例方法的正确方法是 -method:name:include:colons:,而不是 method()。例如,-init 或 -databaseWithPath:,而不是 init() 或 databaseWithPath()。

标签: objective-c cocoa


【解决方案1】:

在我看来,当您第一次尝试创建 EFAPersistance 对象时,您的 AppDelegate 未设置。这是在 AppDelegate.m 的下面一行

self.db = [[EFAPersistence alloc] init];

我想在init 完成(返回)之后设置应用程序委托。

【讨论】:

  • 我也认为 NSApp 是在 init() 之后创建/分配的。问题是如何只在 EFAPersistences 中分配 efaDatabase 一次。还有其他方法,例如 awakeFromNib 和 viewDidLoad 等。但是这些在普通的 NSObject 子类中不可用。
  • @Jens 在我上面提到的那一行之后做self.db.efaDatabase = efaDatabase;怎么样?
  • 在 self.db 上设置 efaDatabase,在实例化它之后,工作。谢谢大家。
【解决方案2】:

这种分配方式行不通。但是,如果我将代码放在正常的方法中,它就会起作用。所以我确信 efaDatabase 已在我的 AppDelegate 中正确实例化。它只是在我的 init() 方法中不起作用。这就是为什么我觉得 NSApp 在 init() 方法中不起作用。

NSApp 工作正常。

引用 epatel:

我想应用程序委托是在初始化完成(返回)后设置的。

正确。 nib 加载器完全实例化每个对象(包括应用程序委托,如果它在一个 nib 中),然后 将其设置为它连接到的任何属性的值。这是两个独立的操作;它不会将尚未初始化的对象设置为应用程序委托。

再次引用你(Jens)的话:

问题是如何在 EFAPersistences 中只分配一次 efaDatabase 。还有其他方法,例如 awakeFromNib 和 viewDidLoad 等。但是这些在普通的 NSObject 子类中不可用。

不正确。 awakeFromNib 在对象初始化后发送到 nib 中的每个对象。

也就是说,我很好奇为什么您的笔尖中有 EFAPersistence。从它的名字看,它听起来与接口无关。应用程序委托不应该拥有 EFAPersistence,而 EFAPersistence 直接拥有数据库吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-21
    • 2020-12-25
    • 2012-02-03
    相关资源
    最近更新 更多