web-dev-qa-db-ja.com

メインキューのperformSelectorOnMainThreadとdispatch_asyncの違いは何ですか?

スレッド内のビューの変更で問題が発生していました。サブビューを追加しようとしましたが、表示に約6秒以上かかりました。ようやく機能しましたが、正確にはわかりません。だから私はそれがなぜ機能し、次の方法の違いは何なのかと思っていました:

//this worked -added the view instantly
dispatch_async(dispatch_get_main_queue(), ^{
    //some UI methods ej
    [view addSubview: otherView];
}

//this took around 6 or more seconds to display
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView
 waitUntilDone:NO];

//Also didnt work: NSNotification methods -  took also around 6 seconds to display
//the observer was in the viewController I wanted to modify
//paired to a method to add a subview.
[[NSNotificationCenter defaultCenter] postNotificationName:
 @"notification-identifier" object:object];

参考のために、これはACAccountStoreのクラスのこのCompletetion Handler内で呼び出されました。

accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
            if(granted) {
            //my methods were here
            }
}

編集:うまくいかなかったと言ったとき、追加したビューを表示するには約6秒かかりました。

53
Miguel Lomelí

デフォルトでは、_-performSelectorOnMainThread:withObject:waitUntilDone:_はデフォルトの実行ループモードで実行するセレクターのみをスケジュールします。実行ループが別のモード(トラッキングモードなど)にある場合、実行ループがデフォルトモードに戻るまで実行されません。バリアント_-performSelectorOnMainThread:withObject:waitUntilDone:modes:_でこれを回避できます(実行するすべてのモードを渡すことにより)。

一方、dispatch_async(dispatch_get_main_queue(), ^{ ... })は、メイン実行ループが制御フローをイベントループに戻すとすぐにブロックを実行します。モードは気にしません。そのため、モードについても気にしたくない場合は、dispatch_async()がより良い方法かもしれません。

70
Lily Ballard

performSelectorOnMainThread:withObject:waitUntilDone:は、一般的な実行ループモードでメッセージをキューに入れます。 AppleのConcurrency Programming Guide によると、メインキューは、キューに入れられたタスクをアプリの実行ループからの他のイベントとインターリーブします。したがって、イベントキューに処理する他のイベントがある場合、後で送信されたとしても、ディスパッチキューのキューに入れられたブロックが最初に実行される可能性があります。

この記事performSelectorOnMainThreaddispatch_async、上記の質問にも答えます。

1
Say2Manuj

waitUntilDone=YESでthe PerformSelectorOnMainThreadを試しましたか

例えば:

コード:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];

PerformSelectorOnMainThreadが応答するのに非常に時間がかかる理由については、これで問題を解決できると思います。

0
Ruchira Randana