あなたの問題はすべて、メインスレッドをブロックしているという事実から来ています。
Cocoa や他のほぼすべての GUI フレームワークでは、メイン スレッドは次のイベントを待機するループを実行し、イベント ハンドラーを呼び出し、終了するまで繰り返します。
イベント ハンドラ はapplicationDidFinishLaunching_
決して戻りません。これは、Cocoa が次のイベントを処理できないことを意味します。最終的に、OS はあなたが応答していないことに気づき、ビーチボールを準備します。
Cocoa では、呼び出しのように、機会を与えるたびに他のイベントに忍び込むことsetTitle_
があります。また、ウィンドウを再描画し続けるなど、応答していなくても OS が偽造できるものがあるため、そうではありません。アプリが応答しないことは常に明らかです。しかし、それは問題を解決する必要がないという意味ではありません。
これを行うにはいくつかの方法がありますが、最も簡単なのはおそらくバックグラウンド スレッドを使用することです。次に、applicationDidFinishLaunching_ はバックグラウンド スレッドを開始してすぐに戻ることができるため、メイン スレッドはジョブ処理イベントに戻ることができます。
唯一の注意点は、バックグラウンド スレッドで実行されているコードが UI オブジェクトを呼び出せないことです。それで、あなたはそれについて何をしますか?
それperformSelectorOnMainThread_withObject_waitUntilDone_
がそのためです。
次に例を示します。
class MyApplicationAppDelegate(NSObject):
var = 1
def background_work(self):
global ngmail
while var == 1 :
ngmail2 = gmail();
if ngmail2 !=ngmail:
self.statusItem.setTitle_("loading")
self.statusItem.performSelectorOnMainThread_withObject_waitUntilDone_('setTitle:', ngmail2, False)
time.sleep(6)
def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")
self.statusItem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength)
self.background_worker = threading.Thread(target=self.background_work)
self.background_worker.start()
setTitle:
唯一のトリッキーな点は、Python の名前 ( ) ではなく、ObjC の名前 ( ) をセレクターに使用する必要があることですsetTitle_
。
ただし、コードには別の微妙なバグvar
があります。実際には同期されていないため、バックグラウンド スレッドが気付かないうちにメイン スレッドでその値を変更する可能性があります。
その上、バックグラウンド スレッドはスリープ状態が終了するまでsleep(6)
チェックするコードに到達しないため、アプリを終了するのに最大 6 秒かかることを意味します。var
を使用して、これらの両方を修正できますCondition
。
class MyApplicationAppDelegate(NSObject):
var = 1
condition = threading.Condition()
def background_work(self):
global ngmail
with condition:
while var == 1:
ngmail2 = gmail();
if ngmail2 != ngmail:
self.statusItem.performSelectorOnMainThread_withObject_waitUntilDone_('setTitle:', ngmail2, False)
condition.wait(6)
@classmethod
def shutdown_background_threads(cls):
with condition:
var = 0
condition.notify_all()
(意図的にインスタンス属性ではなく、クラス属性 for を使用していると思われるvar
ので、同様に条件をクラス属性に、シャットダウン メソッドをクラス メソッドにしました。)