问题
I have an ARC project involving a custom view that appears after clicking a status bar icon. I'm new to programming, so I pulled this example project from GitHub to get up and running. The app runs fine, the only issue is with the status bar item. I set up the NSStatusItem as I should, but as soon as I call setView, the icon seems to be released. I can click an empty space in the menubar which opens the app so the item is there, it's just that the icon is missing. (Image is confirmed to be valid). What am I missing?
Here's the NSStatusItem code:
//
// WOMAppDelegate.m
// PopoverMenulet
//
// Created by Julián Romero on 10/26/11.
// Copyright (c) 2011 Wuonm Web Services S.L. All rights reserved.
//
#import "WOMAppDelegate.h"
#import "WOMMenulet.h"
#import "WOMController.h"
@implementation WOMAppDelegate
@synthesize window = _window;
@synthesize menulet;
@synthesize statusItem;
@synthesize statusImage;
@synthesize controller;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
//SET UP NSSTATUSITEM
statusImage = [NSImage imageNamed:@"basket"];
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[self.statusItem setImage:statusImage];
//[self.statusItem setHighlightMode:YES];
[self.statusItem setEnabled:YES];
self.menulet = [[WOMMenulet alloc] init]; /* square item */
self.controller = [[WOMController alloc] init];
self.menulet.delegate = controller;
[self.statusItem setView:menulet];
}
@end
And here's the referenced menulet code:
//
// WOMMenulet.m
// PopoverMenulet
//
// Created by Julián Romero on 10/26/11.
// Copyright (c) 2011 Wuonm Web Services S.L. All rights reserved.
//
#import "WOMMenulet.h"
static void *kActiveChangedKVO = &kActiveChangedKVO;
@implementation WOMMenulet
@synthesize delegate;
- (void)setDelegate:(id<WOMMenuletDelegate>)newDelegate
{
[(NSObject *)newDelegate addObserver:self forKeyPath:@"active" options:NSKeyValueObservingOptionNew context:kActiveChangedKVO];
delegate = newDelegate;
}
- (void)mouseDown:(NSEvent *)event {
[self.delegate menuletClicked];
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == kActiveChangedKVO) {
//NSLog(@"%@", change);
[self setNeedsDisplay:YES];
}
}
@end
回答1:
the setImage is only valid f or the default view of the NSStatusItem, as soon as you call - setView:
you are setting a custom view to be displayed in the menubar. This custom view should draw the image by itself if you so desire to have an image in the menubar.
This information can be found in the docs, here: NSStatusItem class reference
Pay attention to:
Discussion Setting a custom view overrides all the other appearance and behavior settings defined by NSStatusItem. The custom view is responsible for drawing itself and providing its own behaviors, such as processing mouse clicks and sending action messages.
回答2:
this view will just draw what you set on the item
@interface DDQuickMenuStatusItemView : NSView
@property(weak) NSStatusItem *item;
//...
@end
@implementation DDQuickMenuStatusItemView
//...
- (void)drawRect:(NSRect)dirtyRect {
NSImage *image = nil;
if(self.item) {
[self.item drawStatusBarBackgroundInRect:self.bounds withHighlight:NO];
image = self.item.image;
}
if(image) {
NSRect r = self.bounds;
r.size = [image size];
r = [self.class centerRect:r inRect:self.bounds];
r = [self centerScanRect:r];
[image drawInRect:r fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
}
}
#pragma mark -
+ (CGRect)centerRect:(CGRect)rect inRect:(CGRect)inRect
{
CGRect result = rect;
result.origin.x = inRect.origin.x + (inRect.size.width - result.size.width)*0.5f;
result.origin.y = inRect.origin.y + (inRect.size.height - result.size.height)*0.5f;
return result;
}
@end
回答3:
I went back to the original code from the GitHub repo which, although not pretty I've learned from others, works with a small tweak. Thanks for the help guys, I now know what to do for V2.
来源:https://stackoverflow.com/questions/16522036/nsstatusitem-releases-icon