メインスレッドでメソッドを呼び出しますか?


82

まず、iPhone用のコードを書いています。を使用せずにメインスレッドでメソッドを呼び出せるようにする必要がありますperformSelectorOnMainThread。使用したくない理由performSelectorOnMainThreadは、ユニットテスト用のモックを作成しようとすると問題が発生するためです。

[self performSelectorOnMainThread:@Selector(doSomething) withObject:nil];

問題は、私のモックは電話をかける方法を知っているが、電話doSomethingをかける方法を知らないということperformSelectorOnMainThreadです。

だから何か解決策はありますか?

回答:


272

Objective-C

dispatch_async(dispatch_get_main_queue(), ^{
    [self doSomething];
});

迅速

DispatchQueue.main.async {
    self.doSomething()
}

レガシースウィフト

dispatch_async(dispatch_get_main_queue()) {
    self.doSomething()
}

あなたはちょうど私の一日を迅速な3コードで作りました。ありがとう!
フェリペバルドゥイーノ2016

自己を直接ブロックに使用しないことをお勧めします。代わりに、弱参照を使用してください。
Jageen

2

ソフトウェアには、間接層を追加するとほとんどすべてが修正されるということわざがあります。

doSomethingメソッドを、performSelectorOnMainThreadのみを実行してreally_doSomethingメソッドを呼び出して実際のSomething作業を実行する間接シェルにします。または、doSomethingメソッドを変更したくない場合は、モックテストユニットにdoSomething_redirect_shellメソッドを呼び出して同様のことを実行させます。


1

Swiftでこれを行うためのより良い方法は次のとおりです。

runThisInMainThread { () -> Void in
    // Run your code
    self.doSomething()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

それは私のリポジトリに標準機能として含まれています、それをチェックしてくださいhttps//github.com/goktugyil/EZSwiftExtensions


これは決して良いことではありません。別の関数を呼び出すだけの関数を作成しました。ちなみに、迅速な構文をさらに簡略化できるため、「()-> Void in」は必要ありません
aryaxt 2015

そのより人間的な読み取り/書き込み可能。はい、オートコンプリートは「()->無効」を追加します。void> voidクロージャでこのオートコンプリート動作を無効にする方法はありますか?
esqarrouth 2015

あなたが持っているメソッド名は誤解を招く可能性があり、ブロックはメインスレッドですぐに実行されるように聞こえますが、それは真実ではありません。メインキューのdispatch_asyncは、コードのブロックを次のrunloopに追加します。この重要な動作は、「ru​​nThisInMainThread
aryaxt 2015

1
これは予想される動作です。dispatch_asyncはコードをキューの最後に追加します。すぐに呼び出されるようにする場合は、代わりにdispatch_syncを実行する必要があります。すでに入っているスレッドのキューでdispatch_syncを実行すると、スレッドロックが発生します。あなたの例では、印刷の順序は「a」、「c」、「b」です。aとcは同じスコープ内にあるため、1つの実行ループで実行されます。bはキューの最後に追加されるため、後でキュー内の他の既存のアイテムが完了すると呼び出されることがあります
aryaxt 2015

1
@ Esqarrouth-dispatch_async呼び出し後にブロックされたコードを確認しますか?asyncではなく使用することの全体的なポイントはsync、次のことをブロックしないことです。(もちろん、要求されたコードのポイントはメインスレッドで実行することなので、blockコードのofはメインスレッド上の他のすべてブロックします。バックグラウンドコードを実行する場合は、別のキューを要求します。ではありませんdispatch_get_main_queue。)
ToolmakerSteve 2016

1

そして今Swift3で:

DispatchQueue.main.async{
   self.doSomething()
}

-4
// Draw Line
    func drawPath(from polyStr: String){
        DispatchQueue.main.async {
            let path = GMSPath(fromEncodedPath: polyStr)
            let polyline = GMSPolyline(path: path)
            polyline.strokeWidth = 3.0
            polyline.strokeColor = #colorLiteral(red: 0.05098039216, green: 0.5764705882, blue: 0.2784313725, alpha: 1)
            polyline.map = self.mapVu // Google MapView
        }

    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.