尝试了解如何使用 xib 文件

发布于 2024-12-28 22:48:56 字数 7623 浏览 5 评论 0原文

我有一个在 xib 文件中使用的自定义视图。我加载视图并将其添加到窗口中。它添加了视图,因为我可以在视图中看到标签的默认文本,但是当我尝试通过方法调用更改标签时,它不会更改文本。

自定义视图没什么花哨的,只是绘制一个圆形的透明背景。

NotificationView.h

#import <Cocoa/Cocoa.h>

@interface NotificationView : NSView

@property (weak) IBOutlet NSTextField *primaryLabel;
@property (weak) IBOutlet NSTextField *secondaryLabel;
@property (weak) IBOutlet NSTextField *identifierLabel;

@end

NotificationView.m

@implementation NotificationView
@synthesize primaryLabel;
@synthesize secondaryLabel;
@synthesize identifierLabel;


- (id) initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    if (self)
    {
        return self;
    }
    return nil;
}


- (void)drawRect:(NSRect)dirtyRect
{
    NSColor *bgColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.6];
    NSRect rect = NSMakeRect([self bounds].origin.x + 3, [self bounds].origin.y + 3, [self bounds].size.width - 6, [self bounds].size.height - 6);

    NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:5.0 yRadius:5.0];
    [path addClip];

    NSShadow *shadow = [[NSShadow alloc] init];
    [shadow setShadowColor:[NSColor redColor]];
    [shadow setShadowBlurRadius:2.0f];
    [shadow setShadowOffset:NSMakeSize(0.f, -1.f)];
    [shadow set];

    [bgColor set];
    NSRectFill(rect);

    [super drawRect:dirtyRect];
}

@end

在 xib 中,我有一个设置为 NotificationView 类型的自定义视图。我已向视图添加了 3 个标签,并将它们连接到上面的 IBOutlet。 (我按住 Ctrl 键单击并从标签拖动到 .h 文件以建立连接。)

我正在加载视图并将其添加到使用以下方法的窗口中。它查看窗口数组,如果找到现有匹配项,则使用该窗口,如果没有,则创建一个新窗口。

- (void) popupNotificationWithTag:(NSString *)tag fade:(double)msFade lineOne:(NSString *)lineOneText lineTwo:(NSString *)lineTwoText
{
    NotificationWindow *notificationWindow;
    NotificationWindow *tmpWindow;
    NSEnumerator *enumerator;

    // Walk the notification windows in the array
    enumerator = [self.notificationWindows objectEnumerator];
    if(enumerator)
    {
        while((tmpWindow = [enumerator nextObject]))
        {
            if([tmpWindow.tag isEqualToString:tag])
            {
                notificationWindow = tmpWindow;
            }
        }
    }

    // Make a new notification window
    if (!notificationWindow)
    {
        int width = [[NSScreen mainScreen] frame].size.width;
        int height = [[NSScreen mainScreen] frame].size.height;

        notificationWindow = [[NotificationWindow alloc] initWithRect:NSMakeRect(width - 420, height - 130, 400, 100)];
        NSNib *nib = [[NSNib alloc] initWithNibNamed:@"Notification" bundle: nil];
        NSArray *objects;
        [nib instantiateNibWithOwner:self topLevelObjects:&objects];

        for (id obj in objects) {
            if ([[obj class] isSubclassOfClass:[NSView class]])

                [notificationWindow setContentView:obj];
        }

        [notificationWindow setTag:tag];         
        [self.notificationWindows addObject:notificationWindow];
    }

    // Display window
    [notificationWindow makeKeyAndOrderFront:nil];
    [notificationWindow display];
    notificationWindow.fadeOut = msFade;
    [notificationWindow setPrimaryText:lineOneText];
    [notificationWindow setSecondaryText:lineTwoText];
    [notificationWindow setIdentifierText:tag];
}

窗口类是 NotificationWindow.h

#import <Foundation/Foundation.h>

@interface NotificationWindow : NSWindow

@property (nonatomic, strong) NSString *tag;
@property (nonatomic) double fadeOut;

- (id)initWithRect:(NSRect)contentRect;
- (void) setPrimaryText:(NSString *)text;
- (void) setSecondaryText:(NSString *)text;
- (void) setIdentifierText:(NSString *)text;

@end

NotificationWindow.m

#import "NotificationWindow.h"
#import "NotificationView.h"

//===========================================================================================================================
// Private call properties and methods
//===========================================================================================================================
@interface NotificationWindow()

@property (nonatomic,strong) NSTimer *timerFade;

- (void) timerFadeFired;

@end


//===========================================================================================================================
//===========================================================================================================================


@implementation NotificationWindow

//===========================================================================================================================
// Property Getters and Setters
//===========================================================================================================================
@synthesize tag = _tag;
@synthesize fadeOut = _fadeOut;

@synthesize timerFade = _timerFade;


//===========================================================================================================================
// Public methods
//===========================================================================================================================
- (id)initWithRect:(NSRect)contentRect
{
    if (self = [super initWithContentRect:contentRect 
                                styleMask:NSBorderlessWindowMask 
                                  backing:NSBackingStoreBuffered 
                                    defer:NO]) {
        [self setLevel: NSScreenSaverWindowLevel];
        [self setBackgroundColor: [NSColor clearColor]];
        [self setAlphaValue: 1.0];
        [self setOpaque: NO];
        [self setHasShadow: NO];
        [self setIgnoresMouseEvents: YES];
        [self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
        [self orderFront: NSApp];
        self.fadeOut = -1;

        // Start our timer to deal with fadeing the window
        self.timerFade = [NSTimer scheduledTimerWithTimeInterval:0.001
                                                          target:self
                                                        selector:@selector(timerFadeFired)
                                                        userInfo:nil
                                                         repeats:YES];

        return self;
    }

    return nil;
}


- (BOOL) canBecomeKeyWindow
{
    return YES;
}

- (void) display
{
    [super display];
    [self setAlphaValue:1.0];
}

- (void) setPrimaryText:(NSString *)text
{
    NotificationView *view = self.contentView;
    view.primaryLabel.stringValue = text;
}


- (void) setSecondaryText:(NSString *)text
{
    NotificationView *view = self.contentView;
    view.secondaryLabel.stringValue = text;
}


- (void) setIdentifierText:(NSString *)text
{
    NotificationView *view = self.contentView;
    view.identifierLabel.stringValue = text;
}


//===========================================================================================================================
// Private methods
//===========================================================================================================================
- (void) timerFadeFired
{
    [self orderFront:NSApp];
    if (self.fadeOut > 0)
    {
        self.fadeOut--;
    }
    else if (self.fadeOut == 0)
    {
        if (self.alphaValue > 0)
            self.alphaValue -= 0.002;
        else
            self.fadeOut = -1;
    }
}


@end

所以我认为我在将标签连接到 IBOutlet 时做错了什么,但我不知道是什么。我想我可以在代码中创建视图,但我试图做得更好并使用界面生成器。

我使用的是 XCode 4.2.1。

I have a custom view that I'm using in a xib file. I load the view and add it to a window. It adds the view just fine as I can see the default text of the labels in the view, but when I try to change the label with a method call, it doesn't change the text.

The custom view isn't anything to fancy, just draws a rounded, transparent background.

NotificationView.h

#import <Cocoa/Cocoa.h>

@interface NotificationView : NSView

@property (weak) IBOutlet NSTextField *primaryLabel;
@property (weak) IBOutlet NSTextField *secondaryLabel;
@property (weak) IBOutlet NSTextField *identifierLabel;

@end

NotificationView.m

@implementation NotificationView
@synthesize primaryLabel;
@synthesize secondaryLabel;
@synthesize identifierLabel;


- (id) initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    if (self)
    {
        return self;
    }
    return nil;
}


- (void)drawRect:(NSRect)dirtyRect
{
    NSColor *bgColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.6];
    NSRect rect = NSMakeRect([self bounds].origin.x + 3, [self bounds].origin.y + 3, [self bounds].size.width - 6, [self bounds].size.height - 6);

    NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:5.0 yRadius:5.0];
    [path addClip];

    NSShadow *shadow = [[NSShadow alloc] init];
    [shadow setShadowColor:[NSColor redColor]];
    [shadow setShadowBlurRadius:2.0f];
    [shadow setShadowOffset:NSMakeSize(0.f, -1.f)];
    [shadow set];

    [bgColor set];
    NSRectFill(rect);

    [super drawRect:dirtyRect];
}

@end

In the xib I have a custom view set to the type NotificationView. I've added 3 labels to the view and connected them to the above IBOutlets. (I ctrl-click & drag from the label to the .h file to make the connection.)

I'm loading the view and adding it to a window with the following method. It looks through an array of windows, if an existing match is found it used that window, if not it creates a new window.

- (void) popupNotificationWithTag:(NSString *)tag fade:(double)msFade lineOne:(NSString *)lineOneText lineTwo:(NSString *)lineTwoText
{
    NotificationWindow *notificationWindow;
    NotificationWindow *tmpWindow;
    NSEnumerator *enumerator;

    // Walk the notification windows in the array
    enumerator = [self.notificationWindows objectEnumerator];
    if(enumerator)
    {
        while((tmpWindow = [enumerator nextObject]))
        {
            if([tmpWindow.tag isEqualToString:tag])
            {
                notificationWindow = tmpWindow;
            }
        }
    }

    // Make a new notification window
    if (!notificationWindow)
    {
        int width = [[NSScreen mainScreen] frame].size.width;
        int height = [[NSScreen mainScreen] frame].size.height;

        notificationWindow = [[NotificationWindow alloc] initWithRect:NSMakeRect(width - 420, height - 130, 400, 100)];
        NSNib *nib = [[NSNib alloc] initWithNibNamed:@"Notification" bundle: nil];
        NSArray *objects;
        [nib instantiateNibWithOwner:self topLevelObjects:&objects];

        for (id obj in objects) {
            if ([[obj class] isSubclassOfClass:[NSView class]])

                [notificationWindow setContentView:obj];
        }

        [notificationWindow setTag:tag];         
        [self.notificationWindows addObject:notificationWindow];
    }

    // Display window
    [notificationWindow makeKeyAndOrderFront:nil];
    [notificationWindow display];
    notificationWindow.fadeOut = msFade;
    [notificationWindow setPrimaryText:lineOneText];
    [notificationWindow setSecondaryText:lineTwoText];
    [notificationWindow setIdentifierText:tag];
}

The window class is NotificationWindow.h

#import <Foundation/Foundation.h>

@interface NotificationWindow : NSWindow

@property (nonatomic, strong) NSString *tag;
@property (nonatomic) double fadeOut;

- (id)initWithRect:(NSRect)contentRect;
- (void) setPrimaryText:(NSString *)text;
- (void) setSecondaryText:(NSString *)text;
- (void) setIdentifierText:(NSString *)text;

@end

NotificationWindow.m

#import "NotificationWindow.h"
#import "NotificationView.h"

//===========================================================================================================================
// Private call properties and methods
//===========================================================================================================================
@interface NotificationWindow()

@property (nonatomic,strong) NSTimer *timerFade;

- (void) timerFadeFired;

@end


//===========================================================================================================================
//===========================================================================================================================


@implementation NotificationWindow

//===========================================================================================================================
// Property Getters and Setters
//===========================================================================================================================
@synthesize tag = _tag;
@synthesize fadeOut = _fadeOut;

@synthesize timerFade = _timerFade;


//===========================================================================================================================
// Public methods
//===========================================================================================================================
- (id)initWithRect:(NSRect)contentRect
{
    if (self = [super initWithContentRect:contentRect 
                                styleMask:NSBorderlessWindowMask 
                                  backing:NSBackingStoreBuffered 
                                    defer:NO]) {
        [self setLevel: NSScreenSaverWindowLevel];
        [self setBackgroundColor: [NSColor clearColor]];
        [self setAlphaValue: 1.0];
        [self setOpaque: NO];
        [self setHasShadow: NO];
        [self setIgnoresMouseEvents: YES];
        [self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
        [self orderFront: NSApp];
        self.fadeOut = -1;

        // Start our timer to deal with fadeing the window
        self.timerFade = [NSTimer scheduledTimerWithTimeInterval:0.001
                                                          target:self
                                                        selector:@selector(timerFadeFired)
                                                        userInfo:nil
                                                         repeats:YES];

        return self;
    }

    return nil;
}


- (BOOL) canBecomeKeyWindow
{
    return YES;
}

- (void) display
{
    [super display];
    [self setAlphaValue:1.0];
}

- (void) setPrimaryText:(NSString *)text
{
    NotificationView *view = self.contentView;
    view.primaryLabel.stringValue = text;
}


- (void) setSecondaryText:(NSString *)text
{
    NotificationView *view = self.contentView;
    view.secondaryLabel.stringValue = text;
}


- (void) setIdentifierText:(NSString *)text
{
    NotificationView *view = self.contentView;
    view.identifierLabel.stringValue = text;
}


//===========================================================================================================================
// Private methods
//===========================================================================================================================
- (void) timerFadeFired
{
    [self orderFront:NSApp];
    if (self.fadeOut > 0)
    {
        self.fadeOut--;
    }
    else if (self.fadeOut == 0)
    {
        if (self.alphaValue > 0)
            self.alphaValue -= 0.002;
        else
            self.fadeOut = -1;
    }
}


@end

So I assume I'm doing something wrong connecting the labels to the IBOutlets, but I can't figure out what. I suppose I could create the view in code, but I was trying to be good and use the interface builder.

I'm in XCode 4.2.1.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文