2014-09-12 2 views
1

Я показываю NSPopover в NSView, исходя из точки на NSBezierPath. Я могу показать popover без проблем, но я не могу установить строковое значение двух текстовых полей в нем. Поппер и представление содержимого - это как собственный подкласс NSPopover, так и NSViewController, соответственно. Подкласс NSPopover также является делегатом 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 у меня также есть Object, установленный в WeightPopoverController, с атрибутом dateLabel и weightLabel, подключенным к их текстовым полям, а contentViewController - File's Owner.

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

UPDATE:

Я удалил подкласс 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. Вот почему я думал, что у меня проблема с тем, как я настроил переменные класса/экземпляра.

ответ

0

Вы, кажется, создавая два Popovers, один в коде (popover = [[WeightPopoverController alloc] init]) и один в Interface Builder (В этом XIb я также есть объект установлен на WeightPopoverController). Подумайте о том, чего вы пытаетесь достичь.

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

+0

Спасибо за совет. Я обновил свой вопрос на основе вашего ответа. – user4034838

0

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

К счастью, есть простое решение (as mentioned in this answer): просто вызовите на свой контроллер view геттер, и это заставит представление инициализировать раньше.

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

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: ...];