-
-
Save shakemno/fa4b6ea5909b26ab30eee7f18b7c7872 to your computer and use it in GitHub Desktop.
(iOS) GCD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//https://medium.com/@nimjea/grand-central-dispatch-in-swift-fdfdd8b22d52 | |
DispatchQueue.main.async { | |
// Perform your async code here | |
} | |
//Synced operations | |
let northZone = DispatchQueue(label: "perform_task_with_team_north") | |
//Sync operation | |
// the program waits until execution finishes before the method call returns | |
northZone.sync { | |
for numer in 1...3{ print("North \(numer)")} | |
} | |
//Async operation | |
// executed asynchronously with the async method, the method call returns immediately | |
northZone.async { | |
for numer in 1...3{ print("North \(numer)") } | |
} | |
// Queues: | |
// Global Queue - Using to perform non-UI work in the background | |
// Main Queue - Using to update the UI after completing work in a task on a concurrent queue. | |
//QoS Priorities: | |
/* | |
.userInteractive | |
.userInitiated | |
.default | |
.utility | |
.background | |
.unspecified | |
*/ | |
DispatchQueue.global(qos: .background).async { | |
// Call your background task | |
DispatchQueue.main.async { | |
// UI Updates here for task complete. | |
} | |
} | |
//DispatchQueue with delay | |
let deadlineTime = DispatchTime.now() + .seconds(1) | |
DispatchQueue.main.asyncAfter(deadline: deadlineTime) { | |
//Perform code here | |
} | |
//Dispatch groups | |
let dispatchGroup = DispatchGroup() | |
dispatchGroup.enter() | |
loadUseractivities { dispatchGroup.leave() } | |
dispatchGroup.enter() | |
loaduserComments { dispatchGroup.leave() } | |
dispatchGroup.notify(queue: .main) { | |
print("all activities complete 👍") | |
} | |
//DispatchWorkItem | |
private var pendingRequestWorkItem: DispatchWorkItem? | |
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { | |
// Cancel the currently pending item | |
pendingRequestWorkItem?.cancel() | |
// Wrap our request in a work item | |
let requestWorkItem = DispatchWorkItem { [weak self] in | |
self?.resultsLoader.loadResults(forQuery: searchText) | |
} | |
// Save the new work item and execute it after 250 ms | |
pendingRequestWorkItem = requestWorkItem | |
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(250), | |
execute: requestWorkItem) | |
} | |
//DispatchSemaphore | |
https://medium.com/@roykronenfeld/semaphores-in-swift-e296ea80f860 | |
/* | |
A semaphore consist of a threads queue and a counter value (type Int). | |
Threads queue is used by the semaphore to keep track on waiting threads in FIFO order | |
(The first thread entered to the queue will be the first to get access to the shared resource once it is available). | |
Counter value is used by the semaphore to decide if a thread should get access to a shared resource or not. | |
The counter value changes when we call signal() or wait() functions. | |
wait() -> counter--. if counter < 0 thread is freezed. if counter > 0 execute thread | |
signal() -> counter++. if previousCounter < 0 execute oldest thread in queue. if previousCounter > 0 queue is empty. No one waits | |
*/ | |
//DispatchSemaphore provides a way to synchronously wait for a group of asynchronous tasks. | |
//Calling wait() before a signal() will block the current queue until a signal is received. | |
extension Array where Element == DataSource { | |
func load() throws -> NoteCollection { | |
let semaphore = DispatchSemaphore(value: 0) | |
var loadedCollection: NoteCollection? | |
// We create a new queue to do our work on, since calling wait() on | |
// the semaphore will cause it to block the current queue | |
let loadingQueue = DispatchQueue.global() | |
loadingQueue.async { | |
// We extend 'load' to perform its work on a specific queue | |
self.load(onQueue: loadingQueue) { collection in | |
loadedCollection = collection | |
// Once we're done, we signal the semaphore to unblock its queue | |
semaphore.signal() | |
} | |
} | |
// Wait with a timeout of 5 seconds | |
semaphore.wait(timeout: .now() + 5) | |
guard let collection = loadedCollection else { | |
throw NoteLoadingError.timedOut | |
} | |
return collection | |
} | |
} | |
//Using the above new method on Array | |
//we can now load notes synchronously in a script or command line tool like this: | |
let dataSources: [DataSource] = [ | |
localDataSource, | |
iCloudDataSource, | |
backendDataSource | |
] | |
do { | |
let collection = try dataSources.load() | |
output(collection) | |
} catch { | |
output(error) | |
} | |
//DispatchSource | |
//Observe file changes | |
class FileObserver { | |
private let file: File | |
private let queue: DispatchQueue | |
private var source: DispatchSourceFileSystemObject? | |
init(file: File) { | |
self.file = file | |
self.queue = DispatchQueue(label: "com.myapp.fileObserving") | |
} | |
func start(closure: @escaping () -> Void) { | |
// We can only convert an NSString into a file system representation | |
let path = (file.path as NSString) | |
let fileSystemRepresentation = path.fileSystemRepresentation | |
// Obtain a descriptor from the file system | |
let fileDescriptor = open(fileSystemRepresentation, O_EVTONLY) | |
// Create our dispatch source | |
let source = DispatchSource.makeFileSystemObjectSource( | |
fileDescriptor: fileDescriptor, | |
eventMask: .write, | |
queue: queue | |
) | |
// Assign the closure to it, and resume it to start observing | |
source.setEventHandler(handler: closure) | |
source.resume() | |
self.source = source | |
} | |
} | |
//Use it | |
let observer = try FileObserver(file: file) | |
observer.start { | |
print("File was changed") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment