无法更改辅助 window 面板中的标签
Can't change labels in secondary window panel
我有一个辅助 window(面板),带有一个按钮和一个包含一些标签的框。我需要能够更改框标题和标签文本,但只能在 AwakeFromNIB 中这样做。如果我在 WindowDidLoad 中检查标签的文本,它是零。 Init 正在触发 3 次。
// ExtendedCal.h
#import <Cocoa/Cocoa.h>
@interface ExtendedCal : NSWindowController
@property (retain) IBOutlet NSTextField *lblCCW;
@property (retain) IBOutlet NSTextField *lblCW;
@property (nonatomic, retain) IBOutlet NSTextField *lblDegrees;
@property (nonatomic, retain) IBOutlet NSBox *boxExtCal;
@property (nonatomic, retain) IBOutlet NSButton *btnOK;
@property (nonatomic, retain) NSString *maxSteps;
@property (nonatomic) NSInteger arrayCtr;
@property (nonatomic) NSInteger steps;
- (IBAction)btnOKClicked:(id)sender;
- (void)resetUI;
@end
// ExtendedCal.m
#import "ExtendedCal.h"
NSString * const myExtendedCalChangedNotification = @"MyExtCalKey";
NSString *const myExtendedCalEndedNotification = @"myExtCalEndedKey";
NSMutableArray *pointArray;
NSInteger extCalStep;
NSInteger extCalAxis;
NSInteger extCalMin;
NSInteger extCalMax;
/*
@interface ExtendedCal ()
@end
*/
@implementation ExtendedCal
@synthesize lblDegrees;
@synthesize lblCCW;
@synthesize lblCW;
@synthesize btnOK;
@synthesize boxExtCal;
@synthesize maxSteps;
@synthesize arrayCtr;
@synthesize steps;
- (id)init
{
self = [super initWithWindowNibName:@"ExtendedCal"];
return self;
}
- (void)windowWillLoad
{
[lblDegrees setStringValue:@"MMM"]; /// does nothing
}
- (void)windowDidLoad
{
[super windowDidLoad];
NSInteger var1, ec, tmpI = 0;
steps = 0;
[self resetUI]; //does nothing when called from here
maxSteps = @"16";
ec = 0;
pointArray = [NSMutableArray array];
var1 = 0;
while (var1 <= extCalStep*25)
{
if (extCalMin == var1)
{
ec = 1;
[pointArray addObject:[NSNumber numberWithInteger:var1]];
}
var1 = var1 + extCalStep;
}
if(ec==0)
{
ec = 1;
[pointArray addObject:[NSNumber numberWithInteger:extCalMin]];
}
var1 = extCalStep;
tmpI = [pointArray count];
while (var1 < extCalMax)
{
if (var1 > [[pointArray objectAtIndex:ec - 1]integerValue])
{
ec +=1;
[pointArray addObject:[NSNumber numberWithInteger:var1]];
}
var1 += extCalStep;
}
if(extCalMax > [[pointArray objectAtIndex:ec-1]integerValue])
{
ec +=1;
[pointArray addObject:[NSNumber numberWithInteger:extCalMax]];
}
tmpI = [pointArray count];
arrayCtr = 0;
NSString *str = [[pointArray objectAtIndex:0]stringValue];
[lblDegrees setStringValue:str]; //does nothing
NSString *s2 = [lblDegrees stringValue]; //s2 is nil
}
- (void)awakeFromNib
{
[lblDegrees setStringValue:@"888"]; //works from here
[self resetUI]; //works from here
}
- (void)btnOKClicked:(id)sender
{
extCalStep +=1;
NSMutableString *tmp;
NSString *option = @"160";
tmp = [NSMutableString string];
[tmp setString:@"Calibration-step "];
[tmp appendFormat:@"%ld",extCalStep];
[tmp appendString:@" of "];
[tmp appendString:maxSteps];
[boxExtCal setTitle:tmp]; //does nothing
option = [[pointArray objectAtIndex:arrayCtr] stringValue];
option = [NSString stringWithFormat:@"0%ld", extCalStep];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSDictionary *userInfo = [NSDictionary
dictionaryWithObject:optionforKey:@"myExtCalKey"];
[nc postNotificationName:myExtendedCalChangedNotification
object:self
userInfo:userInfo];
steps++;
}
- (void)resetUI
{
NSMutableString *boxStr = [[NSMutableString alloc] init];
[boxExtCal setTitle:@"Calibration step 1 of 16"];
lblCW.hidden = NO;
lblCCW.hidden = YES;
[boxStr setString:@""];
[boxStr appendString:@"999"];
//[boxStr appendString:@"\u00B0"];
[lblDegrees setStringValue:boxStr];
steps = 0;
}
布线
window被
打开
// ORSSerialPortDemoController.m
#import "Calibrate.h"
#import "ExtendedCal.h"
Calibrate *calibrate;
ExtendedCal *extCal;
@interface ORSSerialPortDemoController () {
}
@end
.
.
.
[extendedcal showWindow:self];
将所有出口从 Extended Cal 更改为 File's Owner,window 除外。
我认为您的问题是您有两个 window 控制器实例 class、ExtendedCal
。您正在通过分配和初始化 class 在代码中创建一个。我怀疑你也在 NIB 本身中实例化了一个。您在自己的回答中几乎证实了这一点,您在 NIB 中提到了 Extended Cal。
在代码中创建的实例是加载 NIB 的实例。当您的 -init
方法调用 super 的 -initWithWindowNibName:
方法时,它会获取传递给它的 NIB 名称。它在第一次请求 window
属性 时加载 NIB,这隐含在对 -showWindow:
.
的调用中
当NSWindowController
(或子class)加载NIB 时,它会将自己传递为所有者。因此,NIB 中的文件所有者占位符解析为该对象。此外,在该实例上调用了 -windowDidLoad
方法。
由于您的 NIB 包含 ExtendedCal
的另一个实例,因此在加载 NIB 时也会创建该实例。但是,它不是 NIB 的所有者,也没有加载 NIB。所以,它的 -windowDidLoad
方法没有被调用。并且与它的任何连接(插座、绑定等)都不会连接到第一个实例。
这两个实例具有不同的角色,其中一个调用了特定的方法,另一个具有各种重要的联系,这是混淆的根源。
您说得对,更改此类连接以连接到文件所有者是解决方案的一部分。其余的解决方案是简单地从 NIB 中完全删除 ExtendedCal
的实例。它不应该在那里。 window 控制器在笔尖之外。它是在加载 NIB 之前创建的,实际上是加载 NIB 的内容。因此,不应在 NIB 中对其进行实例化。
为了进一步讨论,我推荐这篇文章:https://www.mikeash.com/pyblog/friday-qa-2013-04-05-windows-and-window-controllers.html
哦,还有一些事情:
调用 -windowWillLoad
时未加载笔尖。因此,还没有连接任何网点,并且 lblDegrees
应该是 nil
.
我建议避免在 window 控制器上实施 -awakeFromNib
。 -windowDidLoad
是更好的选择。 -awakeFromNib
的问题在于它在某些情况下可以被多次调用(例如,如果您的 window 控制器是基于视图的 table 视图的委托)。 -windowDidLoad
的语义和时间更简单。
我有一个辅助 window(面板),带有一个按钮和一个包含一些标签的框。我需要能够更改框标题和标签文本,但只能在 AwakeFromNIB 中这样做。如果我在 WindowDidLoad 中检查标签的文本,它是零。 Init 正在触发 3 次。
// ExtendedCal.h
#import <Cocoa/Cocoa.h>
@interface ExtendedCal : NSWindowController
@property (retain) IBOutlet NSTextField *lblCCW;
@property (retain) IBOutlet NSTextField *lblCW;
@property (nonatomic, retain) IBOutlet NSTextField *lblDegrees;
@property (nonatomic, retain) IBOutlet NSBox *boxExtCal;
@property (nonatomic, retain) IBOutlet NSButton *btnOK;
@property (nonatomic, retain) NSString *maxSteps;
@property (nonatomic) NSInteger arrayCtr;
@property (nonatomic) NSInteger steps;
- (IBAction)btnOKClicked:(id)sender;
- (void)resetUI;
@end
// ExtendedCal.m
#import "ExtendedCal.h"
NSString * const myExtendedCalChangedNotification = @"MyExtCalKey";
NSString *const myExtendedCalEndedNotification = @"myExtCalEndedKey";
NSMutableArray *pointArray;
NSInteger extCalStep;
NSInteger extCalAxis;
NSInteger extCalMin;
NSInteger extCalMax;
/*
@interface ExtendedCal ()
@end
*/
@implementation ExtendedCal
@synthesize lblDegrees;
@synthesize lblCCW;
@synthesize lblCW;
@synthesize btnOK;
@synthesize boxExtCal;
@synthesize maxSteps;
@synthesize arrayCtr;
@synthesize steps;
- (id)init
{
self = [super initWithWindowNibName:@"ExtendedCal"];
return self;
}
- (void)windowWillLoad
{
[lblDegrees setStringValue:@"MMM"]; /// does nothing
}
- (void)windowDidLoad
{
[super windowDidLoad];
NSInteger var1, ec, tmpI = 0;
steps = 0;
[self resetUI]; //does nothing when called from here
maxSteps = @"16";
ec = 0;
pointArray = [NSMutableArray array];
var1 = 0;
while (var1 <= extCalStep*25)
{
if (extCalMin == var1)
{
ec = 1;
[pointArray addObject:[NSNumber numberWithInteger:var1]];
}
var1 = var1 + extCalStep;
}
if(ec==0)
{
ec = 1;
[pointArray addObject:[NSNumber numberWithInteger:extCalMin]];
}
var1 = extCalStep;
tmpI = [pointArray count];
while (var1 < extCalMax)
{
if (var1 > [[pointArray objectAtIndex:ec - 1]integerValue])
{
ec +=1;
[pointArray addObject:[NSNumber numberWithInteger:var1]];
}
var1 += extCalStep;
}
if(extCalMax > [[pointArray objectAtIndex:ec-1]integerValue])
{
ec +=1;
[pointArray addObject:[NSNumber numberWithInteger:extCalMax]];
}
tmpI = [pointArray count];
arrayCtr = 0;
NSString *str = [[pointArray objectAtIndex:0]stringValue];
[lblDegrees setStringValue:str]; //does nothing
NSString *s2 = [lblDegrees stringValue]; //s2 is nil
}
- (void)awakeFromNib
{
[lblDegrees setStringValue:@"888"]; //works from here
[self resetUI]; //works from here
}
- (void)btnOKClicked:(id)sender
{
extCalStep +=1;
NSMutableString *tmp;
NSString *option = @"160";
tmp = [NSMutableString string];
[tmp setString:@"Calibration-step "];
[tmp appendFormat:@"%ld",extCalStep];
[tmp appendString:@" of "];
[tmp appendString:maxSteps];
[boxExtCal setTitle:tmp]; //does nothing
option = [[pointArray objectAtIndex:arrayCtr] stringValue];
option = [NSString stringWithFormat:@"0%ld", extCalStep];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSDictionary *userInfo = [NSDictionary
dictionaryWithObject:optionforKey:@"myExtCalKey"];
[nc postNotificationName:myExtendedCalChangedNotification
object:self
userInfo:userInfo];
steps++;
}
- (void)resetUI
{
NSMutableString *boxStr = [[NSMutableString alloc] init];
[boxExtCal setTitle:@"Calibration step 1 of 16"];
lblCW.hidden = NO;
lblCCW.hidden = YES;
[boxStr setString:@""];
[boxStr appendString:@"999"];
//[boxStr appendString:@"\u00B0"];
[lblDegrees setStringValue:boxStr];
steps = 0;
}
布线
window被
打开// ORSSerialPortDemoController.m
#import "Calibrate.h"
#import "ExtendedCal.h"
Calibrate *calibrate;
ExtendedCal *extCal;
@interface ORSSerialPortDemoController () {
}
@end
.
.
.
[extendedcal showWindow:self];
将所有出口从 Extended Cal 更改为 File's Owner,window 除外。
我认为您的问题是您有两个 window 控制器实例 class、ExtendedCal
。您正在通过分配和初始化 class 在代码中创建一个。我怀疑你也在 NIB 本身中实例化了一个。您在自己的回答中几乎证实了这一点,您在 NIB 中提到了 Extended Cal。
在代码中创建的实例是加载 NIB 的实例。当您的 -init
方法调用 super 的 -initWithWindowNibName:
方法时,它会获取传递给它的 NIB 名称。它在第一次请求 window
属性 时加载 NIB,这隐含在对 -showWindow:
.
当NSWindowController
(或子class)加载NIB 时,它会将自己传递为所有者。因此,NIB 中的文件所有者占位符解析为该对象。此外,在该实例上调用了 -windowDidLoad
方法。
由于您的 NIB 包含 ExtendedCal
的另一个实例,因此在加载 NIB 时也会创建该实例。但是,它不是 NIB 的所有者,也没有加载 NIB。所以,它的 -windowDidLoad
方法没有被调用。并且与它的任何连接(插座、绑定等)都不会连接到第一个实例。
这两个实例具有不同的角色,其中一个调用了特定的方法,另一个具有各种重要的联系,这是混淆的根源。
您说得对,更改此类连接以连接到文件所有者是解决方案的一部分。其余的解决方案是简单地从 NIB 中完全删除 ExtendedCal
的实例。它不应该在那里。 window 控制器在笔尖之外。它是在加载 NIB 之前创建的,实际上是加载 NIB 的内容。因此,不应在 NIB 中对其进行实例化。
为了进一步讨论,我推荐这篇文章:https://www.mikeash.com/pyblog/friday-qa-2013-04-05-windows-and-window-controllers.html
哦,还有一些事情:
调用 -windowWillLoad
时未加载笔尖。因此,还没有连接任何网点,并且 lblDegrees
应该是 nil
.
我建议避免在 window 控制器上实施 -awakeFromNib
。 -windowDidLoad
是更好的选择。 -awakeFromNib
的问题在于它在某些情况下可以被多次调用(例如,如果您的 window 控制器是基于视图的 table 视图的委托)。 -windowDidLoad
的语义和时间更简单。