在之前一篇日志 里,我简单的介绍了一下如何在项目中增加Growl.framework。现在,我来介绍一下如何使用Growl。在之前的日志里,我演示的时候,是往项目中加入Growl.framework,这次,为了完整起见,我将使用Growl-WithInstaller.framework来演示。
这两个框架的区别在于后者把Growl安装程序打包进了框架中。如果用户没有安装Growl,并且愿意安装,可以马上安装。但是很多人并不喜欢这种捆绑安装的方式,很多人把责任归咎于Growl,Growl甚至专门为此写了个网页 解释。其实Growl是出于好意,并且,选择哪个框架是开发人员的事情。作为用户,如果你真的不喜欢Growl,Growl能够很方便的删除;而作为开发人员,应该根据目标用户谨慎选择捆绑Growl安装程序的包。
好了,题外话不多说,言归正传。
我们首先在Xcode里新建一个简单的Cocoa项目,按照前文的方法,加入Growl支持。
要让Cocoa程序支持Growl,首先要为Growl设置一个Delegate
。简单起见,我们在AppDelegate
的-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
中,设置Delegate
方法:
1
[ GrowlApplicationBridge setGrowlDelegate : self ];
在显示提示信息之前,我们首先要“注册”提示信息。注册的方法有两种,一种是在项目中加入一个名为“Growl Registration Ticket.growlRegDict”的文件,格式为property list。Growl会自动加载这个文件。
这个plist包含三个键值对。第一个键是TicketVersion
,值为整数类型,目前取值为1
;第二个键是AllNotifications
,值为一个数组,其中包含所有的Notification
的名称,类型为字符串;第三个键是DefaultNotifications
,值为一个数组,是AllNotifications
的一个子集,作为默认启用的Notification
。大多数情况下,是相同的。至于为什么要有这两种数组的区分,我也没弄得很明白。
另一种注册提示信息的方法是实现一个delegate
方法:-(NSDictionary *)registrationDictionaryForGrowl
。这个方法返回的辞典必须包含两个键:GROWL_NOTIFICATIONS_ALL
和GROWL_NOTIFICATIONS_DEFAULT
。作用自然不用多说,跟上述的AllNotifications
和DefaultNotifications
一一对应。
1
2
3
4
5
6
- ( NSDictionary * ) registrationDictionaryForGrowl {
NSArray * allNotes = [ NSArray arrayWithObjects : @"myNotification" , @"myNote" , @"notDefaultNote" , nil ];
NSArray * defaultNotes = [ NSArray arrayWithObjects : @"myNotification" , @"myNote" , nil ];
return [ NSDictionary dictionaryWithObjectsAndKeys : allNotes , GROWL_NOTIFICATIONS_ALL , defaultNotes , GROWL_NOTIFICATIONS_DEFAULT , nil ];
}
如果没有利用任何一种方法注册提示信息,程序在编译时,在控制台上会出现下面这样错误信息:
1
2011 - 05 - 26 20 : 08 : 13.469 GrowlTest [ 1644 : 903 ] GrowlApplicationBridge : The Growl delegate did not supply a registration dictionary , and the app bundle at / Users / venj / Library / Developer / Xcode / DerivedData / GrowlTest - hetkeinkpxbuynbhprgdyoywkrif / Build / Products / Debug / GrowlTest . app does not have one . Please tell this application ' s developer .2011 - 05 - 26 20 : 08 : 13.668 GrowlTest [ 1644 : 903 ] not installed
不过Growl提示还是能够显示的。至于注册和不注册的区别,我也没弄明白,囧。
注册完毕之后,你就能显示Growl提示了。我们假设在Cocoa项目中,增加了一个按钮,连接到下面这个Action上:
1
2
3
- ( IBAction ) showGrowl: ( id ) sender {
[ GrowlApplicationBridge notifyWithTitle : @"The Title" description : @"This is a notification description." notificationName : @"myNote" iconData : nil priority : 0 isSticky : NO clickContext : nil ];
}
Growl提示的核心方法是:
1
2
3
4
5
6
7
+ [ GrowlApplicationBridge notifyWithTitle :
description :
notificationName :
iconData :
priority :
isSticky :
clickContext :]
其中,title
(NSString
), description
(NSString
), iconData
(NSData
), isSticky
(BOOL
)的值在下图中表示了一下。其中,Sticky的值如果设置为YES
,那么必须要用户点击关闭按钮,提示才会消失;否则,提示会自动消失。
priority
的取值为包括-2, -1, 0, 1, 2,从左到右优先级递增。Priority通常没啥作用。如果你在Growl的控制面板中,为不同优先级设置了不统的提示背景和提示文字颜色,那么这些优先级就会反映出来。
最后一个context
,接收一个id
类型的值。这个值与-(void)growlNotificationWasClicked:(id)clickContext
这个回调方法有密切联系。如果context
为nil
,这个方法将不会调用;如果context
不是nil
,那么context
的值就会作为clickContext
的值,传入这个回调方法。在Growl提示被点击时候,会触发这个回调方法,执行相应的动作。
另外,还有几个delegate
方法,我来简单介绍一下:
-(void)growlIsReady:
这个方法主要是在程序使用了Growl-WithInstaller.framework时,用户选择安装或升级Growl,并成功启动之后,所执行的动作。
-(void)growlNotificationTimedOut:(id)clickContext:
与-(void)growlNotificationWasClicked:(id)clickContext
类似,这个方法是在用户没有对提示作出响应,在Growl即将消失的时候调用的一个方法。
-(NSData *)applicationIconDataForGrowl
和-(NSString *)applicationNameForGrowl
,设置Growl返回的程序名称和程序图标。通常如果不设置,Growl会使用默认的程序图标和Info.plist
里指定的程序名称。比如下面的两个图中,我们并没有为示例程序设置程序图标,而默认的程序名称为“GrowlAppTest”。我们在实现了这两个方法之后,可以覆盖默认行为,这样,在Growl设置和Growl提示里,我们就能看到图标和程序名称了。
另外,假如用户没有安装Growl,那么应用Grow-WitiInstaller.framework的时候,程序在第一次调用Growl方法的时候会提示用户安装Growl。
关于如何自定义这个对话框“说服”用户安装Growl,还有几个Delegate
方法来做到。我就不一一叙述了:
1
2
3
4
- ( NSString * ) growlInstallationWindowTitle ;
- ( NSString * ) growlUpdateWindowTitle ;
- ( NSAttributedString * ) growlInstallationInformation ;
- ( NSAttributedString * ) growlUpdateInformation ;
最后,我就连篇累牍的奉上示例程序的源代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* GrowlTestAppDelegate.h */
#import <Cocoa/Cocoa.h>
#import "Growl-WithInstaller/Growl.h"
@interface GrowlTestAppDelegate : NSObject < NSApplicationDelegate , GrowlApplicationBridgeDelegate > {
@private
NSWindow * window ;
}
@property ( assign ) IBOutlet NSWindow * window ;
- ( IBAction ) showGrowl: ( id ) sender ;
@end
/* GrowlTestAppDelegate.m */
#import "GrowlTestAppDelegate.h"
@implementation GrowlTestAppDelegate
@synthesize window ;
- ( void ) applicationDidFinishLaunching: ( NSNotification * ) aNotification
{
// Insert code here to initialize your application
[ GrowlApplicationBridge setGrowlDelegate : self ];
if ( ! [ GrowlApplicationBridge isGrowlInstalled ]) {
NSLog ( @"not installed" );
}
}
- ( IBAction ) showGrowl: ( id ) sender {
[ GrowlApplicationBridge notifyWithTitle : @"The Title" description : @"This is a notification description." notificationName : @"myNote" iconData : nil priority : 0 isSticky : NO clickContext : @"God" ];
}
# pragma mark - Growl Delegate
//- (NSDictionary *)registrationDictionaryForGrowl {
// NSArray *allNotes = [NSArray arrayWithObjects:@"myNotification", @"myNote", @"notDefaultNote", nil];
// NSArray *defaultNotes = [NSArray arrayWithObjects:@"myNotification", @"myNote", nil];
//
// return [NSDictionary dictionaryWithObjectsAndKeys:allNotes, GROWL_NOTIFICATIONS_ALL, defaultNotes, GROWL_NOTIFICATIONS_DEFAULT, nil];
//}
- ( void ) growlIsReady {
NSLog ( @"Growl is up and running." );
[ self showGrowl : nil ];
}
- ( void ) growlNotificationTimedOut: ( id ) clickContext {
NSLog ( @"%@, I'm disappearing..." , clickContext );
}
- ( void ) growlNotificationWasClicked: ( id ) clickContext {
NSLog ( @"%@, I'm clicked..." , clickContext );
}
- ( NSData * ) applicationIconDataForGrowl {
NSData * data = [ NSData dataWithContentsOfFile :[[ NSBundle mainBundle ] pathForImageResource : @"lame" ]];
return data ;
}
- ( NSString * ) applicationNameForGrowl {
return @"GrowlAppTest" ;
}
# pragma mark - Growl Installer Delegate
- ( NSString * ) growlInstallationWindowTitle {
return @"Install Growl" ;
}
- ( NSString * ) growlUpdateWindowTitle {
return @"Update Growl" ;
}
//- (NSAttributedString *)growlInstallationInformation {
// // Some inplementation
//}
//
//- (NSAttributedString *)growlUpdateInformation {
// // Some inplementation
//}
@end
(全文完)