Skip to content

Instantly share code, notes, and snippets.

@pablogm
Last active October 10, 2021 06:45
Show Gist options
  • Save pablogm/d20120a97912fea44bed to your computer and use it in GitHub Desktop.
Save pablogm/d20120a97912fea44bed to your computer and use it in GitHub Desktop.
Swift extension to add some methods to the NSThread class to run a block on any thread you have a reference to.
//
// NSThread+blocks.swift
// Swift extensions
//
import Foundation
public typealias Block = @convention(block) () -> Void
extension NSThread {
/**
Perform block on current thread
- parameter block: block to be executed
- parameter wait:
*/
func performBlock(block: Block, waitUntilDone wait: Bool) {
NSThread.performSelector("runBlock:", onThread: self, withObject: block as? AnyObject, waitUntilDone: wait)
}
/**
Perform block on main thread
- parameter block: block to be executed
*/
class func performBlockOnMainThread(block: Block) {
NSThread.mainThread().performBlock(block)
}
/**
Perform block in background thread
- parameter block: block to be executed
*/
class func performBlockInBackground(block: Block) {
NSThread.performSelectorInBackground("runBlock:", withObject: block as? AnyObject)
}
/**
Execute block
- parameter block: block to be executed
*/
class func runBlock(block: Block) {
block()
}
/**
Perform block on current thread
- parameter block: block to be executed
*/
func performBlock(block: Block) {
if NSThread.currentThread().isEqual(self) {
block()
}
else {
self.performBlock(block, waitUntilDone: false)
}
}
/**
Perform block
- parameter block: block to be executed
- parameter delay:
*/
func performBlock(block: Block, afterDelay delay: NSTimeInterval) {
self.performSelector("performBlock:", withObject: block as? AnyObject, afterDelay: delay)
}
}
@basememara
Copy link

Thanks for this. Here's a Swift 3 version:

extension Thread {

    private typealias Block = @convention(block) () -> Void
    
    /**
     Execute block, used internally for async/sync functions.
     
     - parameter block: Process to be executed.
     */
    @objc private func run(block: Block) {
        block()
    }

    /**
     Perform block on current thread asynchronously.
     
     - parameter block: Process to be executed.
     */
    public func async(execute: Block) {
        guard Thread.current != self else { return execute() }
        perform(#selector(run(block:)), on: self, with: execute, waitUntilDone: false)
    }

    /**
     Perform block on current thread synchronously.
     
     - parameter block: Process to be executed.
     */
    public func sync(execute: Block) {
        guard Thread.current != self else { return execute() }
        perform(#selector(run(block:)), on: self, with: execute, waitUntilDone: true)
    }
}

Then you use it like this:

let thread = Thread.current
...
thread.async {
    // Do something
}

@sirvon
Copy link

sirvon commented Feb 26, 2017

Where would I put the extension?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment