无法访问App Delegate属性

时间:2012-10-27 11:07:03

标签: objective-c macos cocoa properties

我正在尝试从另一个类访问我的app委托中的属性(我认为这很简单)但是我在这样做时遇到了麻烦。我的文件目前看起来像这样:

LTAppDelegate.h

#import <Cocoa/Cocoa.h>
#import "Subject.h"

@interface LTAppDelegate : NSObject <NSApplicationDelegate, NSOutlineViewDelegate, NSOutlineViewDataSource, NSMenuDelegate> {

}

@property Subject *selectedSubject;

@end

LTAppDelegate.m

@synthesize selectedSubject;

然后在LTAppDelegate.m中的applicationDidFinishLaunching内设置selectedSubject的值。现在我想从我拥有的另一个类中获取访问权限,这个类名为LTTableViewController并且设置如下:

LTTableViewController.h

#import <Foundation/Foundation.h>
#import "LTAppDelegate.h"
#import "Subject.h"
#import "Note.h"

@interface LTTableViewController : NSObject{
    NSMutableArray *notesArray;
    LTAppDelegate *appDelegate;
    Subject *s;
}

-(IBAction)currentSubjectDetails:(id)sender;

@end

LTTableViewController.m

#import "LTTableViewController.h"

@implementation LTTableViewController

- (id)init
{
    self = [super init];
    if (self) {
        appDelegate = ((LTAppDelegate *)[[NSApplication sharedApplication] delegate]);

        s = [appDelegate selectedSubject];
        NSLog(@"Test Subject: %@", [s title]);

    }
    return self;
}

-(IBAction)currentSubjectDetails:(id)sender{
    NSLog(@"Selected Subject: %@", [s title]);

}

在插入各种NSLog()消息之后,似乎在LTAppDelegate中调用applicationDidFinishLaunching之前调用了LTTableViewController的init方法。基于此,有意义的是LTTableViewController.m init中的“Test Subject”NSLog()显示为null;但是,'currentSubjectDetails'方法链接到接口上的按钮,当应用程序加载完成后按下该按钮时,NSLog()消息仍然返回null。

这里有什么明显的遗漏吗?我觉得我有点愚蠢,缺少一些非常基本的东西。

3 个答案:

答案 0 :(得分:2)

此处描述了类似的问题http://iphonedevsdk.com/forum/iphone-sdk-development/11537-viewcontroller-called-before-applicationdidfinishlaunching.html通常不建议在构造函数中添加此类功能。一般来说,我建议使用参数而不是依赖于隐藏的依赖关系,因为这些依赖于执行的顺序,并且你会失去编译器的帮助以避免无效的值。视图控制器初始值设定项不应用于存储可变引用,因为视图控制器由预定义的构造函数自动初始化,并且您不能以这种方式将参数传递给它们。

如果您需要访问应用程序委托,则获取它,对其执行操作并删除引用。尽量不要缓存它,你很可能会引入隐藏的问题。如果查看的内容依赖于任何类型的当前状态,我建议您进入出现消失周期。

答案 1 :(得分:1)

嗯,s不存在,因为它在init中设置为null,因此-currentSubjectDetails打印为null。如果它们依赖于其他对象,那么在构造函数中设置私有变量并不是一个好主意。

相反,让其他对象明确告诉您的控制器它应该使用Subject(例如,将s视为属性)。

或者,每次只查询((LTAppDelegate *)[[NSApplication sharedApplication] delegate]);

答案 2 :(得分:1)

-applicationDidFinishLaunching在调用时调用所有nib的对象都已初始化,因此在构建视图相关内容后将启动启动。这意味着nib对象的构造函数不会使用任何其他nib的对象(你的委托和控制器用nib初始化,对吧?)。

尝试使用-awakeFromNib而不是构造函数,我认为它将在构造两个对象后调用。

如果您试图避免经常调用((LTAppDelegate *)[[NSApplication sharedApplication] delegate])我建议将其作为方法参数传递给函数堆栈。循环引用防御和一些灵活性。