2012-01-15 84 views
9

在几个月没有处理任何东西之后,我开始回到Cocoa开发中。最初,当我开始使用Snow Leopard和Xcode 3时,我现在正在用Xcode 4.2运行Lion,并且遇到了一些我以前没有遇到的问题。NSStatusItem在发布时会短暂出现,但会立即消失

我相信这可能是我以前从未使用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 

编辑如果你看到什么错我的代码,请让我知道。我肯定会有一些批评,这样我才能变得更好。

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

+0

对您的代码的建议:使用[appBundle imageForResource:@“statusItemIcon”]而不是您当前的图片加载代码。它应该更快,支持@ 2x图像透明,支持非PNG没有代码更改,并且更容易阅读:) – 2012-01-15 21:19:26

+0

@Catfish_Man谢谢!这正是我正在寻找的那种批评! – 2012-01-15 21:25:40

回答

16

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

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

这将返回一个自动释放对象。 _statusItem只是一个iVar。不仅如此,但你申报财产的分配:

@property (assign) NSStatusItem *statusItem; 

你可能想在这里做的是使财产strong然后,而不是直接设置实例变量,使用属性来设置。所以像这样:

@property (strong) NSStatusItem *statusItem; 

然后:

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

这将导致statusItem被保留。我敢打赌,现在发生的事情是,当autorelease池弹出时它会被释放,然后当下次尝试访问它时,你的应用程序崩溃,从而导致它从菜单栏中消失。通过僵尸工具运行它肯定会告诉你是否发生了这种情况。但总体而言,您的应用需要对该对象有强烈的参考,才能坚持。

+0

谢谢。我改变了财产强大,它很好。按照预期的方式工作,我是否应该删除iVar并直接使用该属性?这样做的好处是什么? – 2012-01-15 21:56:28

+1

伊娃支持财产。 @synthesized属性已经生成了setter和getter方法,用于处理可以在子类中重写的内存管理需求。一般来说,除非有特定的原因(例如性能,即紧密循环),否则我会说使用除-init和-dealloc之外的setter/getter方法。也就是说,ARC应该能够从其属性声明中推断合成伊娃的内存管理行为,因此假设该属性被声明为“强”,那么直接使用伊娃也应该可行。 – ipmcc 2012-01-15 22:06:32

+1

在ARC之前的日子里,您将不得不使用setter/getters来获得“免费”的内存管理行为。直接访问伊娃时,您需要手动提供等效的内存管理行为。我仍然主要使用非ARC代码库,所以这是我最初的评论来自的地方。 – ipmcc 2012-01-15 22:08:31

0

我在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时并没有持续。