2012-01-15 83 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時並沒有持續。