实例变量在 initWithNib 之后和 NSViewController 中的 IBAction 之前丢失值
我正在编写的 OS X 应用程序有一个非常基本的初始化问题。我正在 NSViewController 中的 initWithNibName 中初始化实例变量。然而,当我在 IBAction 方法中访问它们时,这些变量失去了它们的值并最终等于 nil。
这是我的代码。我有一个应用程序,有 1 个主窗口和 1 个 NSViewController。应用程序委托在 applicationDidFinishLoading 中以编程方式调用 initWithNibName。视图出现,视图中的按钮成功调用onButtonClick。但是,在该方法中,myString 的值为 null。日志清楚地表明它在 initWithNibName 方法期间已成功初始化。所以它在 initWithNibName 和按钮单击之间失去了它的值。
//MyAppDelegate.m
@implementation MyAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
MainView* mainViewController = [[MainView alloc] initWithNibName:@"MainView" bundle:[NSBundle mainBundle]];
[mainViewController loadView];
NSView *controllerView = [mainViewController view];
[window setContentView:controllerView];
}
@end
//MainView.h
@interface MainView : NSViewController {
NSButton *myButton;
NSString* myString;
}
@property (assign) IBOutlet NSButton *myButton;
@property (assign) NSString* myString;
- (IBAction)onMyButtonClick:(id)sender;
@end
//MainView.m
@implementation MainView
@synthesize myButton;
@synthesize myString;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(@"initWithNibName");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
NSLog(@"Initializing...");
[self setMyString:@"try to set the variable"];
NSLog(@"String is %@", myString);
}
return self;
}
- (void)awakeFromNib {
NSLog(@"awakeFromNib");
//[self setMyString:@"init in here works, but is called too many times"];
}
- (IBAction)onMyButtonClick:(id)sender{
NSLog(@"Button clicked");
NSLog(@"%@", myString); //Always nil when initialized in initWithNibName()!!
}
@end
//Logs
initWithNibName
Initializing...
String is try to set the variable
awakeFromNib
awakeFromNib
Button clicked
(null)
如何让 myString 保留其值?
我已经尝试过我能想到的所有类型的财产申报。我还尝试了各种赋值方法([self setMyString]、self.myString = @"blah"、myString = [NSString stringWithFormat:@"blah"] 等)。
我读到我应该在 awakeFromNib() 中进行初始化。这确实有效。然而,我最终的初始化代码将包括一系列 [[MyObj alloc] init] 调用,当它们被多次调用时,会产生多个指针,这就是疯狂。我的最终目标是拥有一个指向对象的指针,控制器始终可以引用该对象并始终获取相同的数据。该对象由控制器初始化,控制器保存引用并在用户与控制器交互时根据需要更新它。
那么有没有办法只初始化 NSViewController 中的实例变量一次,并让它们在控制器的生命周期内保留其值?
谢谢凯夫
I have a very basic initialization problem with an OS X app I am writing. I am initializing instance variables in initWithNibName in my NSViewController. However, these variables lose their value and end up being equal to nil by the time I access them in my IBAction methods.
Here is my code. I have an application that has 1 main window, and 1 NSViewController. The app delegate is programatically calling initWithNibName in applicationDidFinishLoading. The view appears, and the button in the view successfully calls onButtonClick. However, in that method, the value of myString is null. The logs clearly show that it was successfully initialized during the initWithNibName method. So it lost its value between initWithNibName and the button click.
//MyAppDelegate.m
@implementation MyAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
MainView* mainViewController = [[MainView alloc] initWithNibName:@"MainView" bundle:[NSBundle mainBundle]];
[mainViewController loadView];
NSView *controllerView = [mainViewController view];
[window setContentView:controllerView];
}
@end
//MainView.h
@interface MainView : NSViewController {
NSButton *myButton;
NSString* myString;
}
@property (assign) IBOutlet NSButton *myButton;
@property (assign) NSString* myString;
- (IBAction)onMyButtonClick:(id)sender;
@end
//MainView.m
@implementation MainView
@synthesize myButton;
@synthesize myString;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(@"initWithNibName");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
NSLog(@"Initializing...");
[self setMyString:@"try to set the variable"];
NSLog(@"String is %@", myString);
}
return self;
}
- (void)awakeFromNib {
NSLog(@"awakeFromNib");
//[self setMyString:@"init in here works, but is called too many times"];
}
- (IBAction)onMyButtonClick:(id)sender{
NSLog(@"Button clicked");
NSLog(@"%@", myString); //Always nil when initialized in initWithNibName()!!
}
@end
//Logs
initWithNibName
Initializing...
String is try to set the variable
awakeFromNib
awakeFromNib
Button clicked
(null)
How can I get myString to retain its value?
I have tried every type of property declaration I can think of. I have also tried various methods of assignment ([self setMyString], self.myString = @"blah", myString = [NSString stringWithFormat:@"blah"], etc).
I have read that I should do my initialization in awakeFromNib(). This actually does work. However, my eventual initialization code will include a series of [[MyObj alloc] init] calls, and when they get called multiple times, multiple pointers result and it's madness from there. My end goal is to have one pointer to an object, which the controller can always refer to and always get the same data. The object gets initialized by the controller, which holds the reference and updates it as needed as the user interacts with the controller.
So is there any way to initialize instance variables in NSViewControllers, only once, and have them retain their value for the life of the controller?
Thanks
Kev
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该将属性声明为(复制)而不是(分配)
You should declare the property as (copy) instead of (assign)
您是否尝试过将它们声明为(非原子,保留)?
Have you tried declaring them as (nonatomic, retain)?
请允许我回答这个问题,因为正确的答案隐藏在我的问题的评论中。
我知道我做错了什么。我向每个笔尖添加一个视图控制器,代表视图的控制器。然后我将按钮点击附加到该单独的视图控制器对象。 @Francis-McGrew 附加了一个项目,该项目向我展示了我应该将按钮单击附加到文件所有者,然后将文件所有者设置为视图控制器。当您只需使用文件所有者作为占位符时,基本上不需要将第二个视图控制器导入到笔尖中。
Allow me to answer this since the correct answer is buried in the comments in my question.
I figured out what I was doing wrong. I was adding a view controller to each of my nibs that represented the controller for the view. Then I was attaching the button clicks to that separate view controller object. @Francis-McGrew attached a project that showed me that I should be attaching the button clicks to the File Owner, then setting the file owner to be the view controller. There is basically no need to import a second view controller into the nib when you can just use file owner as a placeholder instead.