【问题标题】:Can't change labels in secondary window panel无法更改辅助窗口面板中的标签
【发布时间】:2015-01-18 05:42:12
【问题描述】:

我有一个带有按钮的辅助窗口(面板)和一个包含一些标签的框。我需要能够更改框标题和标签文本,但只能在 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;
}

接线

窗口被打开

//  ORSSerialPortDemoController.m

#import "Calibrate.h"
#import "ExtendedCal.h"

Calibrate *calibrate;
ExtendedCal *extCal;
@interface ORSSerialPortDemoController () {
}   
@end
.
.
.
[extendedcal showWindow:self]; 

【问题讨论】:

    标签: objective-c cocoa


    【解决方案1】:

    我认为您的问题是您的窗口控制器类有两个实例ExtendedCal。您正在通过分配和初始化类在代码中创建一个。我怀疑您在 NIB 本身中也有一个实例化。你几乎用你的自我回答来证实这一点,你提到在你的NIB中有扩展校准。

    在代码中创建的实例是加载 NIB 的对象。当您的-init 方法调用super 的-initWithWindowNibName: 方法时,它会获取传递给它的NIB 名称。它在第一次请求其window 属性时加载NIB,这隐含在对-showWindow: 的调用中。

    NSWindowController(或子类)加载NIB时,它会将自己作为所有者传递。因此,NIB 中的文件所有者占位符解析为该对象。此外,在该实例上调用 -windowDidLoad 方法。

    由于您的 NIB 包含另一个 ExtendedCal 实例,因此在加载 NIB 时也会创建该实例。但是,它不是 NIB 的所有者,也没有加载 NIB。所以,它的-windowDidLoad 方法没有被调用。并且与它的任何连接(插座、绑定等)都不会连接到第一个实例。

    让两个实例具有不同的角色,其中一个具有调用的某些方法,而另一个具有各种重要的连接,这是混乱的根源。

    您是正确的,更改此类连接以连接到文件所有者是解决方案的一部分。解决方案的其余部分是从 NIB 中完全删除 ExtendedCal 的实例。它不应该在那里。窗口控制器位于NIB 之外。它是在加载 NIB 之前创建的,实际上是加载 NIB 的内容。因此,它不应该在 NIB 中实例化。

    为了进一步讨论,我推荐这篇文章:https://www.mikeash.com/pyblog/friday-qa-2013-04-05-windows-and-window-controllers.html


    哦,还有一些其他的事情:

    调用-windowWillLoad 时未加载NIB。因此,尚未连接任何插座,lblDegrees 应该是nil

    我建议避免在窗口控制器上实现-awakeFromNib-windowDidLoad 是更好的选择。 -awakeFromNib 的问题在于它可以在某些情况下被多次调用(例如,如果您的窗口控制器是基于视图的表视图的委托)。 -windowDidLoad 的语义和时序更简单。

    【讨论】:

    • 我认为你是对的,但我不明白如何/在哪里从笔尖中删除 ExtendedCal 的实例化。重置插座似乎已经治愈了所有的弊病,但我可能会遗漏一些东西。
    • 只需在 NIB 的对象列表中选择 Extended Cal 对象。您可能需要编辑器 > 显示文档大纲以使其更清晰。选择对象后,执行 Edit > Delete 将其删除。
    • 感谢您精心制作答案和链接。
    【解决方案2】:

    将所有出口从扩展校准更改为文件所有者,除了窗口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-20
      • 2015-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多