我想调整在所有警报中自动显示的NSApplicationIcon图像,使其与应用程序包中的图像不同。
我知道可以使用[NSApplication setApplicationIconImage:]设置停靠图标 - 但这只会影响停靠,而不会影响停靠。
我可以在某些时候解决这个问题:我有一个NSAlert *,我可以调用setIcon:来显示我的替代图像。
不幸的是,我有很多nibs与NSApplicationIcon一起使用NSImageView,我想要影响它,创建插座并输入代码来改变图标会很麻烦。对于我提出的关于BeginAlert ...类型调用的任何警报(不会给NSAlert对象进行捣乱),我完全没有运气。
任何人都可以想到一种合理的方式来全局(对于正在运行的应用程序的生命周期)覆盖AppKit使用的NSApplicationIcon,并使用我自己的图像,这样我就可以获得100%的警报替换(并使我的代码更简单)?
答案 0 :(得分:1)
调动[NSImage imageNamed:]
方法?这种方法至少适用于Snow Leopard,YMMV。
在NSImage
类别中:
@implementation NSImage (Magic)
+ (void)load {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// have to call imageNamed: once prior to swizzling to avoid infinite loop
[[NSApplication sharedApplication] applicationIconImage];
// swizzle!
NSError *error = nil;
if (![NSImage jr_swizzleClassMethod:@selector(imageNamed:) withClassMethod:@selector(_sensible_imageNamed:) error:&error])
NSLog(@"couldn't swizzle imageNamed: application icons will not update: %@", error);
[pool release];
}
+ (id)_sensible_imageNamed:(NSString *)name {
if ([name isEqualToString:@"NSApplicationIcon"])
return [[NSApplication sharedApplication] applicationIconImage];
return [self _sensible_imageNamed:name];
}
@end
这个被黑了(未经测试,只是写了)jr_swizzleClassMethod:...
实现:
+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ {
#if OBJC_API_VERSION >= 2
Method origMethod = class_getClassMethod(self, origSel_);
if (!origMethod) {
SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]);
return NO;
}
Method altMethod = class_getClassMethod(self, altSel_);
if (!altMethod) {
SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]);
return NO;
}
id metaClass = objc_getMetaClass(class_getName(self));
class_addMethod(metaClass,
origSel_,
class_getMethodImplementation(metaClass, origSel_),
method_getTypeEncoding(origMethod));
class_addMethod(metaClass,
altSel_,
class_getMethodImplementation(metaClass, altSel_),
method_getTypeEncoding(altMethod));
method_exchangeImplementations(class_getClassMethod(self, origSel_), class_getClassMethod(self, altSel_));
return YES;
#else
assert(0);
return NO;
#endif
}
然后,这个方法来说明要点:
- (void)doMagic:(id)sender {
static int i = 0;
i = (i+1) % 2;
if (i)
[[NSApplication sharedApplication] setApplicationIconImage:[NSImage imageNamed:NSImageNameBonjour]];
else
[[NSApplication sharedApplication] setApplicationIconImage:[NSImage imageNamed:NSImageNameDotMac]];
// any pre-populated image views have to be set to nil first, otherwise their icon won't change
// [imageView setImage:nil];
// [imageView setImage:[NSImage imageNamed:NSImageNameApplicationIcon]];
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"Shazam!"];
[alert runModal];
}
有几点需要注意:
setImage:
,如上所示注册图像更改。不知道为什么。imageNamed:
进行初始@"NSApplicationIcon"
来电,而不是我的做法。答案 1 :(得分:0)
尝试[myImage setName:@"NSApplicationIcon"]
(在将其设置为NSApp中的应用程序图标图像后)。
注意:在10.6及更高版本中,您可以而且应该使用NSImageNameApplicationIcon
而不是字符串文字@"NSApplicationIcon"
。