ホームページ>開発ツール>Xojo / Real Studio Trial and Error・CocoaのDeclareで通知センターを利用する
Xojo / Real Studio Trial and Error
目次
CocoaのDeclareで通知センターを利用する
はじめに
今迄、Real Studio(Xojo)の標準機能で実現できないケースでは、主にDeclareを使ってきましたが、それらは全てCarbonベースのものでした。
それがここ最近、使いたい機能が(探し方の問題なのかもしれませんが)Carbonでは見つからず、Cocoaでなら見つかる、という事例も増えてきていることから、CocoaベースのDeclareについて、少し調べてみました。
なお検証には、Real Studio 2011 Release 3を用いています。(Mac mini + OS X 10.8 Mountain Lion)
CocoaのDeclare記述
CocoaのDeclare記述は、Carbonとはちょっと違いますので、まず始めにメモっておきます。
Objective-cでは、一般に、オブジェクトにメッセージを送るという形で式を記述します。
個々のメッセージは、メッセージセレクタ/セレクタ/メソッド名等と呼ばれるが、ここでは主に、Real Studioに合わせてセレクタと呼ぶ。そのため、オブジェクトの取得、セレクタの宣言、セレクタの処理、という3段階が必要になります。
注)オブジェクトの取得はクラスメソッドの場合のみ必要。(インタンスメソッドは、通常それより前に取得したインスタンスに対しての操作になるため。)他に、気付いた点としては、// 下行は、Objective-cでの記述 // NSApplication *sA = [NSApplication sharedApplication]; // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr // 1. NSApplicationオブジェクトを取得 Dim sA As Ptr = NSClassFromString("NSApplication") // 2. NSApplicationのセレクタであるsharedApplicationを宣言 Declare Function SharedApplication Lib "Cocoa" Selector "sharedApplication" (receiver As Ptr) As Ptr // 3. sharedApplicationセレクタの処理(引数にはメッセージの受け手であるsAを指定し、戻り値は同じくsAを指定。) sA = SharedApplication(sA)
- オブジェクト用変数の型はPtrとする。(ネット上ではIntegerを使っているものも見かけるが、Ptr型が導入される以前のやり方?)
- Declare文で使用する「名前(FunctionやSubの次にくる単語)」は任意。セレクタ名と一致していてもよい。(名前を考える手間を省ける。)
- セレクタ名(Selectorの後のダブルクォート部)は空白を含まないこと。(セレクタが複数列挙される場合も同様。)
- セレクタ名の後のカッコの中は、まずメッセージの受け手(以下の例ではreceiver)がきて、(もしあれば)セレクタの引数(以下の例ではid1とid2)がくる。
Declare Function dateWithTimeInterval Lib "Cocoa" Selector "dateWithTimeInterval:sinceDate:" (receiver As Ptr, id1 As Double, id2 As Ptr) As Ptr
- Objective-c側の引数がNSStringの場合は、セレクタの型をCFStringRefにしておくと、Real StudioのString型(変数またはダブルクォートで囲んだ文字列)で渡せる。
Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr Dim sA As Ptr = NSClassFromString("NSApplication")
通知センターを使ってみる
Real Studio(Xojo)言語リファレンスのDeclareの項には、About Boxを表示するサンプルが載っていますが、ここでは、通知センターを使ってみることにしました。
通知センターは、10.8 Mountain Lionから導入された、メールやアップデートのお知らせが画面右上に表示されたり、メニューバー右端の(三の字に似た)アイコンをクリックすると一覧が表示される、というものです。(詳細はこちら。)
Cocoa(Objective-c)では、以下のようなシンプルなコードで実現可能です。(以下は一例です。)
- (void)sendNotification { NSUserNotification *notification = [[NSUserNotification alloc] init]; [notification setTitle:@"Hello World"]; [notification setInformativeText:@"my message"]; [notification setDeliveryDate:[NSDate dateWithTimeInterval:5 sinceDate:[NSDate date]]]; [notification setSoundName:NSUserNotificationDefaultSoundName]; NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; [center scheduleNotification:notification]; }
Real Studioでの実装
以下は、上記Objective-cのコードを、原則としてそのまま移植したものです。
(NSUserNotificationDefaultSoundNameのみ、戻り値であるDefaultSoundNameを直接指定しています。)
上記メソッドを、(例えば)Windowに置いたPushButtonのActionイベントから呼び出します。メソッド名: SendNotification(注:名前は任意) Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr Dim notification As Ptr = NSClassFromString("NSUserNotification") Declare Function notificationAlloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr notification = notificationAlloc(notification) Declare Function notificationInit Lib "Cocoa" Selector "init" (receiver As Ptr) As Ptr notification = notificationInit(notification) Declare Sub setTitle Lib "Cocoa" Selector "setTitle:" (receiver As Ptr, id As CFStringRef) setTitle(notification, "Hello World") Declare Sub setInformativeText Lib "Cocoa" Selector "setInformativeText:" (receiver As Ptr, id As CFStringRef) setInformativeText(notification, "my message") Dim date1 As Ptr = NSClassFromString("NSDate") Declare Function date Lib "Cocoa" Selector "date" (receiver As Ptr) As Ptr date1 = date(date1) Dim date2 As Ptr = NSClassFromString("NSDate") Declare Function dateWithTimeInterval Lib "Cocoa" Selector "dateWithTimeInterval:sinceDate:" (receiver As Ptr, id1 As Double, id2 As Ptr) As Ptr date2 = dateWithTimeInterval(date2,5,date1) Declare Sub setDeliveryDate Lib "Cocoa" Selector "setDeliveryDate:" (receiver As Ptr, id As Ptr) setDeliveryDate(notification, date2) Declare Sub setSoundName Lib "Cocoa" Selector "setSoundName:" (receiver As Ptr, id As CFStringRef) setSoundName(notification, "DefaultSoundName") Dim center As Ptr = NSClassFromString("NSUserNotificationCenter") Declare Function defaultUserNotificationCenter Lib "Cocoa" Selector "defaultUserNotificationCenter" (receiver As Ptr) As Ptr center = defaultUserNotificationCenter(center) Declare Sub scheduleNotification Lib "Cocoa" Selector "scheduleNotification:" (receiver As Ptr, id As Ptr) scheduleNotification(center, notification)
あと、Appの「Application Identifier」に、適切な文字列を設定します。(空欄だと、動作しない。)
何か適当な文字を打ち込んで、その後削除すると、com.yourcompany.yourappnameがデフォルトでセットされるようになるが、それでも問題ないようだ。実行した結果、とりあえず動きました。
問題点
前項で、とりあえず、と書いたのは、「通知がバナー表示されない」ことによります。
メニューバー右端のアイコンをクリックして通知センターを表示してみると、一覧には上がっているので、動作はしているとみてよさそうです。
調べてみたら、以下のサイトがヒットしました。
参考サイト(1):objective c - Send notification to Mountain lion notification center - Stack Overflow
つまり、「(指定をしなければ)通知を発行したアプリ(自分自身)が最前面にあると、通知が表示されない」ということのようです。
そこで、送信後、直ちに別アプリ(またはFinder)をクリックしたところ、バナーが表示されるようになりました。
なお、この問題を回避する方法も、上記参考サイト(1)に記載されていますが、delegateメソッドをオーバーライドする方式のため、Real Studioでの実装方法が分かりません。
アプリの種類によっては、発行後バックグラウンドにまわすとか、直ちに終了するとかで、この問題を迂回することもできそうですが、いずれにしても、もう少し調べてみたいと思います。
追記:delegateメソッドのオーバーライドについて、こちらのページに纏めました。
考察
CocoaのDeclareは、Cocoaでビルドしないと使えないかと思っていたのですが、Carbonでもビルドできました。
今回の通知センターアプリも、Carbonビルドで動作しています。
ただし、上でも触れたAbout Boxを表示するサンプルでは、パネルを閉じられなくなる、という問題が発生しました。
なので、過去の資産を(安定性を重視して)Carbonでビルドしたい場合は、十分テストした方がよさそうです。
macoslibについて
注)この項のみ、Real Studio 2012 Release 2を使用しています。(2011 Release 3では動作しませんでした。)本家のTwitterでも紹介されていたmacoslibを使えば、本件で目指していることが実現できることを確認しました。
勿論、delegateメソッドをオーバーライドする部分も実装されています。
delegateメソッドオーバーライドの仕組みを理解するため、当該部分を実験的に抜きだしてみようかと思ったのですが、複数のクラスやモジュール等が絡み合っていて、一筋縄ではいきそうもありませんでした。実用が目的であれば、素直に使わせて頂いた方が良さそうです。
お世話になったサイト
貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)
参考サイト(1):objective c - Send notification to Mountain lion notification center - Stack Overflow
更新履歴
2015.02.27 問題点の記述に、追記を追加
2014.11.05 CocoaのDeclare記述に、注を追加
2014.03.20 macoslibについて、を追加
2013.09.02 新規作成
[Home] [MacSoft] [Donation] [History] [Privacy Policy] [Affiliate Policy]