【问题标题】:NSStatusItem appears briefly on launch, but promptly disappearsNSStatusItem 在启动时短暂出现,但很快消失
【发布时间】:2012-01-15 21:12:25
【问题描述】:

在几个月没有做任何事情之后,我开始重新投入 Cocoa 开发。一开始我使用的是 Snow Leopard 和 Xcode 3。我现在正在使用 Xcode 4.2 运行 Lion,并且遇到了一些我以前没有遇到过的问题。

我相信这可能是因为我以前从未使用过 ARC,所以我确定我错过了一些东西。

我正在尝试创建没有主窗口或停靠图标的状态栏应用程序。当我运行应用程序时,我的应用程序的状态栏图标会短暂出现大约一秒钟,然后消失。

这是我的代码。

QuickPlusAppDelegate.h

#import <Cocoa/Cocoa.h>

@interface QuickPlusAppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;
@property (assign) NSStatusItem *statusItem;
@property (weak) IBOutlet NSMenu *statusItemMenu;

@property (strong) NSImage *statusItemIcon;
@property (strong) NSImage *statusItemIconHighlighted;
@property (strong) NSImage *statusItemIconNewNotification;

@end

QuickPlusAppDelegate.m

#import "QuickPlusAppDelegate.h"

@implementation QuickPlusAppDelegate
@synthesize statusItemMenu = _statusItemMenu;

@synthesize window = _window, statusItem = _statusItem;
@synthesize statusItemIcon = _statusItemIcon, 
    statusItemIconHighlighted = _statusItemIconHighlighted, 
    statusItemIconNewNotification = _statusItemIconNewNotification;

- (void) awakeFromNib
{
    NSBundle *appBundle = [NSBundle mainBundle];
    _statusItemIcon = [[NSImage alloc] initWithContentsOfFile:[appBundle pathForResource:@"statusItemIcon" ofType:@"png"]];
    _statusItemIconHighlighted = [[NSImage alloc] initWithContentsOfFile:[appBundle pathForResource:@"statusItemIconHighlighted" ofType:@"png"]];
    _statusItemIconNewNotification = [[NSImage alloc] initWithContentsOfFile:[appBundle pathForResource:@"statusItemIconNewNotification" ofType:@"png"]];

    _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    [_statusItem setImage:_statusItemIcon];
    [_statusItem setAlternateImage:_statusItemIconHighlighted];
    [_statusItem setHighlightMode:YES];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // empty
}

@end

编辑如果您发现我的代码有任何问题,请告诉我。我肯定会接受一些批评,这样我才能变得更好。

另一个编辑当主窗口本身加载时,状态栏图标似乎消失了。

【问题讨论】:

  • 对您的代码的建议:使用 [appBundle imageForResource:@"statusItemIcon"] 而不是您当前的图像加载代码。它应该更快,透明支持@2x图像,支持非png无需更改代码,并且更易于阅读:)
  • @Catfish_Man 谢谢!这正是我正在寻找的那种批评!

标签: objective-c cocoa automatic-ref-counting nsstatusbar


【解决方案1】:

_statusItem 在这种情况下会被自动释放。

    _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];

这将返回一个自动释放的对象。 _statusItem 只是一个 iVar。不仅如此,您还将该属性声明为 assign:

@property (assign) NSStatusItem *statusItem;

您可能想要在这里做的是创建属性strong,然后使用该属性来设置它,而不是直接设置 ivar。像这样:

@property (strong) NSStatusItem *statusItem;

然后:

self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];

这将导致 statusItem 被保留。我敢打赌,现在发生的事情是它在自动释放池弹出时被释放,然后你的应用程序在下次尝试访问它时崩溃,从而导致它从菜单栏中消失。通过 Zombies 仪器运行它会确定是否发生了这种情况。但一般来说,您的应用程序需要对该对象具有强引用才能使其保持不变。

【讨论】:

  • 谢谢。我将属性更改为 strong 并且效果很好。随着它按预期方式工作,我是否仍应删除 iVar 并直接使用该属性?这样做有什么好处?
  • ivar 支持该属性。 @synthesized 属性生成了 setter 和 getter 方法来处理可能在子类中被覆盖的内存管理要求。一般来说,我会说在 -init 和 -dealloc 之外的任何地方使用 setter/getter 方法,除非有特定的理由不这样做(比如性能,即紧密循环)。也就是说,ARC 应该能够从其属性声明中推断出合成 ivar 的内存管理行为,因此直接使用 ivar 也应该可以工作,假设属性声明为 strong
  • 在 ARC 之前的日子里,您必须使用 setter/getter 来“免费”获得内存管理行为。当直接访问 ivar 时,您需要手动提供等效的内存管理行为。我仍然主要使用非 ARC 代码库,所以这就是我最初评论的来源。
【解决方案2】:

我在 Xamarin 中遇到了这个问题。有一段时间它工作得很好。然后我在FinishedLaunching 方法中添加了额外的代码,StatusItem 开始消失。我让这段代码生成了 StatusItem:

    public override void AwakeFromNib ()
    {
        var statusItem = NSStatusBar.SystemStatusBar.CreateStatusItem (30);
        statusItem.Menu = mainMenu;
        statusItem.Image = NSImage.ImageNamed ("menuicon");
        statusItem.AlternateImage = NSImage.ImageNamed ("menuicon_selected");
        statusItem.HighlightMode = true;
    }

最终,我发现了我的问题。在我的 Xcode 中,我在 AppDelegate 中声明了这个属性,但我没有使用它:

@property(nonatomic, retain) IBOutlet NSStatusItem *statusItem;

当我删除var 时,StatusItem 继续展现其无限的荣耀:)

    public override void AwakeFromNib ()
    {
        statusItem = NSStatusBar.SystemStatusBar.CreateStatusItem (30);
        statusItem.Menu = mainMenu;
        statusItem.Image = NSImage.ImageNamed ("menuicon");
        statusItem.AlternateImage = NSImage.ImageNamed ("menuicon_selected");
        statusItem.HighlightMode = true;
    }

我不必将其更改为(强)。事实上,我尝试过,但复制回 Xamarin Studio 时它并没有持续存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-21
    • 2023-03-20
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多