在主线程上调用方法?

首先,我正在为 iphone 编写代码。 我需要能够不使用 performSelectorOnMainThread调用主线程上的方法。 我不想使用 performSelectorOnMainThread的原因是,当我试图创建单元测试模拟时,它会导致问题。

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

问题是我的模拟程序知道如何调用 doSomething,但不知道如何调用 performSelectorOnMainThread

有什么办法吗?

89565 次浏览

There's a saying in software that adding a layer of indirection will fix almost anything.

Have the doSomething method be an indirection shell that only does a performSelectorOnMainThread to call the really_doSomething method to do the actual Something work. Or, if you don't want to change your doSomething method, have the mock test unit call a doSomething_redirect_shell method to do something similar.

Objective-C

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

Swift

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

Legacy Swift

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

Here is a better way to do this in Swift:

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


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

Its included as a standard function in my repo, check it out: https://github.com/goktugyil/EZSwiftExtensions

And now in Swift 3:

DispatchQueue.main.async{
self.doSomething()
}
// 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
}


}

The modern Swift solution is to use actors for safe multithreading, namely the MainActor.

@MainActor func setImage(thumbnailName: String) {
myImageView.image = UIImage(image: thumbnailName)
}

I've outlined more actor-based main thread solutions here.