Невозможно установить контент в NSPopover

Я показываю NSPopover в NSView, происходящий из точки на NSBezierPath. Я могу показать поповер без проблем, но я не могу установить строковое значение двух текстовых полей в нем. Всплывающее окно и представление контента являются пользовательским подклассом NSPopover и NSViewController соответственно. Подкласс NSPopover также является делегатом NSPopover, хотя я не использую методы делегатов, поэтому я не уверен, что мне даже нужно это делать.

Вот мой подкласс NSViewController:

#import <Cocoa/Cocoa.h>

@interface WeightPopoverViewController : NSViewController
@end

#import "WeightPopoverViewController.h"
@interface WeightPopoverViewController ()
@end

@implementation WeightPopoverViewController
- (id)init {  
  self = [super initWithNibName:@"WeightPopoverViewController" bundle:nil];
  if (self) {
  }
  return self;
}
@end

И мой подкласс NSPopover:

#import <Cocoa/Cocoa.h>

@interface WeightPopoverController : NSPopover <NSPopoverDelegate> {
  NSTextField *dateLabel;
  NSTextField *weightLabel;
}
@property (strong) IBOutlet NSTextField *dateLabel;
@property (strong) IBOutlet NSTextField *weightLabel;
@end

#import "WeightPopoverController.h"

@implementation WeightPopoverController
@synthesize weightLabel;
@synthesize dateLabel;
@end

Это код в моем подклассе NSView, который открывает поповер:

@interface WeightGraphViewController () {
  WeightPopoverController *popover;
  WeightPopoverViewController *vc;
}

...

-(void)mouseEntered:(NSEvent *)theEvent {

  // initialize the popover and its view controller
  vc = [[WeightPopoverViewController alloc] init];
  popover = [[WeightPopoverController alloc] init];

  // configure popover
  [popover setContentViewController:vc];
  [popover setDelegate:popover];
  [popover setAnimates:NO];

  // set labels
  for (id key in (id)[theEvent userData]) {
    [popover.weightLabel setStringValue:[(NSDictionary*)[theEvent userData] objectForKey:key]];
    [popover.dateLabel setStringValue:key];
  }

  // set the location
  (redacted, irrelevant)

  // show popover
  [popover showRelativeToRect:rect ofView:[self window].contentView preferredEdge:NSMaxYEdge];
}

-(void)mouseExited:(NSEvent *)theEvent {

  [popover close];
  popover = nil;
}

В WeightPopoverViewController.xibЯ установил File's Owner в WeightPopoverViewController и подключил вид к пользовательскому NSView. В этом xib у меня также есть объект, установленный в WeightPopoverController с dateLabel и weightLabel, подключенными к их текстовым полям, и contentViewController установлен в File's Owner,

Я думаю, что то, что я делаю не так, вероятно, связано с тем, как я настроил переменные моего класса / экземпляра для NSPopover, но из проведенного мною исследования и прочитанной документации я не могу понять, куда я пошел неправильно. Любая помощь будет оценена.

ОБНОВИТЬ:

Я удалил подкласс NSPopover из кода и из IB. Я поместил свои розетки в мой NSViewController и соединил их в IB. Тем не менее, я до сих пор не могу установить строковые значения. Следующее не скомпилируется с ошибкой "Свойство weightLabel не найдено для объекта типа NSPopover*".

@interface WeightGraphViewController () {
  NSPopover *popover;
  ...
}

-(void)mouseEntered:(NSEvent *)theEvent {

  vc = [[WeightPopoverViewController alloc] init];
  popover = [[NSPopover alloc] init];
  [popover setContentViewController:vc];
  [popover.dateLabel setStringValue:@"test"];
}

У меня есть определение свойства точно так же, как оно было в моем подклассе NSPopover, но теперь в моем NSViewController. Это на самом деле то, что у меня было раньше, и, поскольку я не смог установить свойства из NSViewController, я решил, что мне нужно сделать это через подкласс NSPopover. Вот почему у меня возникла проблема с настройкой переменных класса / экземпляра.

2 ответа

Вы, кажется, создаете два popovers, один в коде (popover = [[WeightPopoverController alloc] init]) и один в Интерфейсном Разработчике (В этом xib у меня также есть Объект, установленный в WeightPopoverController). Подумайте о том, чего вы пытаетесь достичь.

Я бы также советовал против подклассов NSPopover, Я считаю, что это вызывает путаницу и не является необходимым. Вместо этого поставьте розетки на ваш dateLabel а также weightLabel в контроллере представления контента поповера.

Я испытал нечто похожее. Основная проблема заключается в том, что "выходы", соединяющие ваше представление (XIB) с вашим контроллером, не инициализируются до тех пор, пока представление не будет отображено. Если контроллер пытается установить свойства для каких-либо элементов управления пользовательского интерфейса в представлении до открытия всплывающего окна, эти изменения игнорируются (поскольку все элементы управления будут нулевыми).

К счастью, есть простое решение ( как уже упоминалось в этом ответе): просто вызовите view getter на вашем контроллере, и он заставит представление инициализироваться раньше.

Другими словами:

popover = [NSPopover new];
myController = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil];
popover.contentViewController = myController;

[myController view];  // force view to initialize
...set some values on myController...  // works because view is now loaded

[popover showRelativeToRect: ...];
Другие вопросы по тегам