Swift function does not return soon enough - ios

I'm trying to move my app over to MVC, I have a Parse query which I've moved over to a function in my model class, the function returns a Bool.
When the button in my ViewController below is pressed the model function 'parseQuery' should be run, return a bool and then I need to use that bool to continue. At the moment, the if statement is executed before the function has completed so it always detects false.
How can I ensure that the if statement is completed once the function has completed?
#IBAction func showAllExpiredUsers(sender: AnyObject) {
var success = searchResults.parseQuery()
if success {
print("true")
} else {
print("false")
}
//I have also tried:
searchResults.parseQuery()
if searchResults.parseQuery() {
print("true")
} else {
print("false")
}

You have a few options, but the issue is due to asynchronous calls.
Does Parse expose the same function, with a completion block?
If yes, then you place the processing of the Bool inside the completion block, which is called when the async task is completed.
If not, which I doubt, you could create an NSOperationQueue, with a maxConcurrency of 1 (so it is serial) and dispatch the calls onto the queue with
func addOperationWithBlock(_ block: () -> Void)
This is called on the queue. You would need to store the success bool globally so that you can access it inside the second queued block operation, to check the success state.
Update:
I haven't used parse, but checking the documentation for findObjectsInBackgroundWithBlock (https://parse.com/docs/ios/guide#queries) it takes a completion block where you can process the result, update your bool.
I'm not sure what you are trying to do. You don't need to have the success state of the query. You can check
if (!error) {
// do stuff
} else {
//error occurred - print("error \(error.localizedDescription)"
}
Check the example.
What you need to understand is threading. The async task provides a completion block because its asynchronous, it gets dispatched onto another thread for processing. I'm not sure how much you know about threading but there is something called a thread pool. This thread pool is accessed by Queues. The thread pool is managed by the OS, and makes sure available threads can be used by queues that need work done. As users interact with an application, this (and all UI work) is done on the main thread.
So whenever some processing is going to interfere with possible interaction or UI updates, it should be dispatched (Grand Central Dispatch) or queued (NSOperationQueue, built on top of GCD) off of the main thread.
Anyway, this is why the findObjectsInBackgroundWithBlock call is dispatched off the main thread, because otherwise it would block the main thread until its done, ruining the experience for the user. Also, if the main thread is blocked for more than 1 minute (last time I checked), the OS's watchdog will kill your process.
So yeah, assigning a boolean to the return of the block, would get the return of the function, which occurs before the completion block is done. The completion block is where you code some stuff to be done after the function completes. So the query gets dispatched onto another thread and starts processing, the thread that sent this work off for processing, continues with the rest of its execution. So checking the boolean directly after, wouldn't work because the other thread isn't complete. Even if the other thread finished in time, what is connecting the background thread with the main thread?
This is the beauty of blocks (function pointers), it's a lot cleaner and optimized and keeps code compact. The old way, which is still is use for some older frameworks, is delegates, which detaches the calling code with the callback and adds a delegate dependency. Blocks are beautiful.
Its also important to note that completion blocks don't always get called on the main thread. In many cases its up to you to dispatch the work back to the main thread, to handle any UI work that needs to be done with the objects available inside the completion block.

The query likely takes some time to run and should be run in a background thread with a callback function to handle the response WHEN it completes.
look at the Documentation
Specifically looking at the query.findObjectsInBackgroundWithBlock code:
var query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
print(object.objectId)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo!)")
}
}
The above code will execute the query and run the code in the block when it gets the results from Parse. This is known as an asynchronous task, for more information check out this guide

Related

Is asynchronous code always run on a different thread?

I really think that if code in Swift in iOS runs asynchronously, then it is by the nature of itself that it runs on a separate thread than the thread the code is called from - usually the main thread. It seems obvious to me, but I am uncertain and would like to receive verification of this. I can't think of any conditions in which an asynchronous code would run on the same code that it was called from. It seems almost a certainty by definition that an asynchronous code runs on a different thread than the thread it was called from.
What do you think? Would you agree and verify this?
I ask this question while trying to understand the #escaping keyword as it applies to completion handlers. The Swift documentation on Closuressays that the #escaping keyword causes the completion handler that is designated as escaping to run asynchronously and to run after the function (that receives the completion closure as an argument) finishes running. The documentation, however, does not say whether the escaping completion handler runs on a different thread or on the current thread - which would be the main/UI thread.
I'm trying to hunt where a run-time error is coming from. The error message says: "Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread."
It might be coming from the completion handler of CNContactStore requestAccess(for:completionHandler:), but I need to know if #escaping causes the closure it applies to to run on a different thread than the thread the closure was called from, since the completionHandler parameter is defined as escaping by the #escaping keyword in the definition of CNContactStore requestAccess(for:completionHandler:).
Is the error I'm getting coming from code inside the completion handler of that function that modifies the layout engine or any completion handler marked as escaping?
These posts on stackoverflow helped me clarify my question, but they do not answer my question:
Does Asynchronous code run in the UI thread or a new/different thread to not block the UI?
async - stay on the current thread?
#escaping does NOT determine which thread the closure is ran on. The documentation does.
For that specific function (https://developer.apple.com/documentation/contacts/cncontactstore/1402873-requestaccess/):
The system executes completionHandler on an arbitrary queue. It is recommended that you use CNContactStore instance methods in this completion handler instead of the UI main thread.
If you are doing any sort of UI work inside of the completionHandler callback, it means you MUST call DispatchQueue.main.async { update_my_UI_here() } to execute your code safely on the main thread.
Example:
requestAccess(for: .contacts) { [weak self] permissionGranted, error in
//All code in here is ran on an ARBITRARY background queue
if let error = error {
log(error)
return
}
//CNContactStore - Any CNContactStore functions should run here, and not inside `DispatchQueue.main`
guard let self = self else { return }
// Any UI updates or any code that interacts with `UI*` or constraints, must be done on main
DispatchQueue.main.async {
self.update_my_ui_here(permisionGranted) //Safely update UI from the main queue
}
}
Marking a function as #escaping just means that it may POTENTIALLY be called at a later time or stored as a variable somewhere. That's all it means. It does NOT mean that is will be ran on the same OR a different thread. It doesn't have any guarantees about threads and it doesn't have any guarantees about when it will run.
After all, DispatchQueue.main.async(completion: #escaping () -> Void) has an escaping parameter, and yet it always runs the completion on the exact same main thread. main is the only queue with such guarantee, regardless of whether the parameter is escaping or not.

Swift + Async: How to execute a callback on the same thread where it was created?

Using the Async library, a simple pattern to do work on a background thread might look like this:
// Assume we start on the main thread
let onResultComplete: (result: ResultType) -> Void = { result in
Async.main {
// Code to handle one result at a time on the main thread
}
}
Async.background {
doCalculationsThatProduceManyResults(onEachResultComplete: onResultComplete)
}
Now consider this scenario, where the code is already being executed on a background thread:
// Assume we start on some "unknown background thread"
let onResultComplete: (result: ResultType) -> Void = { result in
Async.??? {
// Code to handle one result at a time on the "unknown background thread"
}
}
Async.background {
doCalculationsThatProduceManyResults(onEachResultComplete: onResultComplete)
}
How can I force the closure onResultComplete to be run on the same unknown background thread from where I called Async.background?
I'm open to any suggestions that use GCD methods.
On iOS or macOS, if some code executes on an unknown thread or dispatch queue (say: "execution context"), there's no means to reliable obtain some "handle" for it - well, unless this is the main thread.
So, the solution to your problem is to first create or obtain a known execution context (aka dispatch queue or thread) and execute your code here. Then, in the continuation (aka completion handler), explicitly dispatch back to this same execution context again and continue with your code.
Don't call Async.anything. Simply run the code in-line (assuming the Async library calls it's completion block on the same thread where the calculations are run.
Your question is specific to the Async library, so you should put that in your title and add a tag for it. (I've never used it, so I don't know the specifics of how it works.)

Understanding why I need to dispatch back to main thread

I just wanted to clear up something that feels a bit unclear for me. Consider the following code that executes a closure asynchronously:
func fetchImage(completion: UIImage? -> ()) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {
// fetch the image data over the internet
// ... assume I got the data
let image = UIImage(data: data)
dispatch_async(dispatch_get_main_queue()) {
completion(image)
}
}
}
To my understanding, the reason we need to dispatch back to the main thread is because it would otherwise take longer to call the completion closure to give back the image.
However, I feel that perspective is a bit cheesy. For example, I'd also like to create a isLoading property that would be used to prevent multiple network calls from happening at the same time:
func fetchImage(completion: UIImage? -> ()) {
// if isLoading is true, then don't continue getting the image because I want only 1 network operation to be running at 1 time.
if isLoading {
completion(nil)
return
}
isLoading = true
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {
let image = UIImage(data: data)
// image creation is complete. Set isLoading to false to allow new fetches
self.isLoading = false
dispatch_async(dispatch_get_main_queue()) {
completion(image)
}
}
}
For this above snippet, my question is - Should I place self.isLoading = false in the dispatch block to the main queue? Or is it insignificant?
All advice appreciated!
It isn't that "it would otherwise take longer", it is that all updates to the UI must be performed on the main queue to prevent corruption that may occur from concurrent updates to the autolayout environment or other UI datastructures that aren't thread-safe.
In prior versions of iOS a common side effect of not updating the UI on the main thread was a delay in that upgrade appearing, however as of iOS 9 you will get an exception.
In terms of your question, it is best that your code behaves consistently. I.e. Either always dispatch the completion handler on the main queue or never do so. This will allow the programmer who is writing the completion block to know whether they need to dispatch UI updates or not.
It is probably best to set isLoading to false as soon as the load has finished, so outside the dispatch_async is best.
Given that your function is retrieving a UIImage there is a good chance that the caller will be updating the UI, so it is probably 'nice' to dispatch the completion handler on the main thread.
To fetch the image from internet in background you simply need to do an async request, you don't need to do it in the background queue as you are doing now.
On the main thread you basically need to do all that things about UI manipulation, because it always run on main thread. This is the important part.
So, the request completion block (the one you'll use to fetch the image) is executed in background (since it is async) and here, inside the block, you need to get the main thread to set the image for the UIImageView for instance.
Other properties than the ones directly related to UI element doesn't needs to be on the main thread as far as I know and I have never had a problem this way.

Managing asynchronous calls to web API in iOS

I am fetching data (news articles) in JSON format from a web service. The fetched data needs to be converted to an Article object and that object should be stored or updated in the database. I am using Alamofire for sending requests to the server and Core Data for database management.
My approach to this was to create a DataFetcher class for fetching JSON data and converting it to Article object:
class DataFetcher {
var delegate:DataFetcherDelegate?
func fetchArticlesFromUrl(url:String, andCategory category:ArticleCategory) {
//convert json to article
//send articles to delegate
getJsonFromUrl(url) { (json:JSON?,error:NSError?) in
if error != nil {
print("An error occured while fetching json : \(error)")
}
if json != nil {
let articles = self.getArticleFromJson(json!,andCategory: category)
self.delegate?.receivedNewArticles(articles, fromCategory: category)
}
}
}
After I fetch the data I send it to DataImporter class to store it in database:
func receivedNewArticles(articles: [Article], fromCategory category:ArticleCategory) {
//update the database with new articles
//send articles to delegate
delegate?.receivedUpdatedArticles(articles, fromCategory:category)
}
The DataImporter class sends the articles to its delegate that is in my case the ViewController. This pattern was good when I had only one API call to make (that is fetchArticles), but now I need to make another call to the API for fetching categories. This call needs to be executed before the fetchArticles call in the ViewController.
This is the viewDidLoad method of my viewController:
override func viewDidLoad() {
super.viewDidLoad()
self.dataFetcher = DataFetcher()
let dataImporter = DataImporter()
dataImporter.delegate = self
self.dataFetcher?.delegate = dataImporter
self.loadCategories()
self.loadArticles()
}
My questions are:
What is the best way to ensure that one the call to the API gets executed before the other one?
Is the pattern that I implemented good since I need to make different method for different API calls?
What is the best way to ensure that one the call to the API gets executed before the other one?
If you want to ensure that two or more asynchronous functions execute sequentially, you should first remember this:
If you implement a function which calls an asynchronous function, the calling function becomes asynchronous as well.
An asynchronous function should have a means to signal the caller that it has finished.
If you look at the network function getJsonFromUrl - which is an asynchronous function - it has a completion handler parameter which is one approach to signal the caller that the underlying task (a network request) has finished.
Now, fetchArticlesFromUrl calls the asynchronous function getJsonFromUrl and thus becomes asynchronous as well. However, in your current implementation it has no means to signal the caller that its underlying task (getJsonFromUrl) has finished. So, you first need to fix this, for example, through adding an appropriate completion handler and ensuring that the completion handler will eventually be called from within the body.
The same is true for your function loadArticles and loadCategories. I assume, these are asynchronous and require a means to signal the caller that the underlying task has finished - for example, by adding a completion handler parameter.
Once you have a number of asynchronous functions, you can chain them - that is, they will be called sequentially:
Given, two asynchronous functions:
func loadCategories(completion: (AnyObject?, ErrorType?) -> ())
func loadArticles(completion: (AnyObject?, ErrorType?) -> ())
Call them as shown below:
loadCategories { (categories, error) in
if let categories = categories {
// do something with categories:
...
// Now, call loadArticles:
loadArticles { (articles, error) in
if let articles = articles {
// do something with the articles
...
} else {
// handle error:
...
}
}
} else {
// handler error
...
}
}
Is the pattern that I implemented good since I need to make different method for different API calls?
IMHO, you should not merge two functions into one where one performs the network request and the other processes the returned data. Just let them separated. The reason is, you might want to explicitly specify the "execution context" - that is, the dispatch queue, where you want the code to be executed. Usually, Core Data, CPU bound functions and network functions should not or cannot share the same dispatch queue - possibly also due to concurrency constraints. Due to this, you may want to have control over where your code executes through a parameter which specifies a dispatch queue.
If processing data may take perceivable time (e.g. > 100ms) don't hesitate and execute it asynchronously on a dedicated queue (not the main queue). Chain several asynchronous functions as shown above.
So, your code may consist of four asynchronous functions, network request 1, process data 1, network request 2, process data 2. Possibly, you need another function specifically for storing the data into Core Data.
Other hints:
Unless there's a parameter which can be set by the caller and which explicitly specifies the "execution context" (e.g. a dispatch queue) where the completion handler should be called on, it is preferred to submit the call of the completion handler on a concurrent global dispatch queue. This performs faster and avoids dead locks. This is in contrast to Alamofire that usually calls the completion handlers on the main thread per default and is prone to dead locks and also performs suboptimal. If you can configure the queue where the completion handler will be executed, please do this.
Prefere to execute functions and code on a dispatch queue which is not associated to the main thread - e.g. not the main queue. In your code, it seems, the bulk of processing the data will be executed on the main thread. Just ensure that UIKit methods will execute on the main thread.

GCD serial queue does not seem to execute serially

I have a method that at times can be invoked throughout my code. Below is a very basic example, as the code processes images and files off of the iphone photo gallery and marks them already processed when done with the method.
#property (nonatomic, assign) dispatch_queue_t serialQueue;
....
-(void)processImages
{
dispatch_async(self.serialQueue, ^{
//block to process images
NSLog(#"In processImages");
....
NSLog(#"Done with processImages");
});
}
I would think that each time this method is called I would get the below output...
"In processImages"
"Done with processImages"
"In processImages"
"Done with processImages"
etc...
but I always get
"In processImages"
"In processImages"
"Done with processImages"
"Done with processImages"
etc...
I thought a serial queue would wait till the first block is done, then start. To me it seems it is starting the method, then it gets called again and starts up before the first call even finishes, creating duplicates of images that normally would not be processed due to the fact that if it really executed serially the method would know they were already processed. Maybe my understanding of serial queues is not concrete. Any input? Thank you.
EDIT:MORE Context below, this is what is going on in the block...Could this cause the issue???
#property (nonatomic, assign) dispatch_queue_t serialQueue;
....
-(void)processImages
{
dispatch_async(self.serialQueue, ^{
//library is a reference to ALAssetsLibrary object
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
....
//Process the photos here
}];
failureBlock:^(NSError *error) { NSLog(#"Error loading images from library");
}];
});
}
-(id)init
{
self = [super init];
if(self)
{
_serialQueue = dispatch_queue_create("com.image.queue",NULL);
}
return self;
}
this object is only created once, and as far as I can tell can never be created again based off my code...I will run tests to make sure though.
UPDATE 2: WHAT I THINK IS HAPPENING, please comment on this if you agree/disagree....
Obviously my main issue is that it seems this block of code is being executed concurrently, creating duplicate entries (importing the same photo twice) when it wouldn't normally do this if it was run serially. When a photo is processed a "dirty" bit is applied to it ensuring the next time the method is invoked it skips this image, but this is not happening and some images are processed twice. Could this be due to the fact I am enumerating the objects in a second queue using enumerategroupswithtypes: within that serialQueue?
call processImages
enumerateObjects
immediately return from enumerateObjects since it is async itself
end call to processImages
processImages is not really done though due to the fact that enumerategroups is probably still running but the queue might thing it is done since it reaches the end of the block before enumerategroups is finished working. This seems like a possibility to me?
Serial Queues ABSOLUTELY will perform serially. They are not guaranteed to perform on the same thread however.
Assuming you are using the same serial queue, the problems is that NSLog is NOT guaranteed to output results in the proper order when called near simultaneously from different threads.
here is an example:
SQ runs on thread X, sends "In processImages"
log prints "In proc"
SQ on thread X, sends "Done with processImages"
SQ runs on thread Y, sends "In processImages"
log prints "essImages\n"
After 5., NSLog doesn't necessarily know which to print, 3. or 4.
If you absolutely need time ordered logging, You need a dedicated queue for logging. In practice, I've had no problems with just using the main queue:
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"whatever");
});
If all NSlog calls are the on the same queue, you shouldn't have this problem.
enumerateGroupsWithTypes:usingBlock:failureBlock: does its work asynchronously on another thread and calls the blocks passed in when it's done (on the main thread I think). Looking at it from another perspective, if it completed all the synchronously by the time the method call was complete, it could just return an enumerator object of the groups instead, for instance, for a simpler API.
From the documentation:
This method is asynchronous. When groups are enumerated, the user may be asked to confirm the application's access to the data; the method, though, returns immediately. You should perform whatever work you want with the assets in enumerationBlock.
I'm not sure why you're trying to accomplish by using the serial queue, but if you just want to prevent simultaneous access, then you could just add a variable somewhere that keeps track of whether we're currently enumerating or not and check that at first, if you don't have to worry about synchronization issues. (If you do, perhaps you should look into using a GCD group, but it's probably overkill for this situation.)
If the question is "Can serial queue perform tasks asynchronously?" then the answer is no.
If you think that it can, you should make sure that all tasks are really performing on the same queue. You can add the following line in the block and compare the output:
dispatch_async(self.serialQueue, ^{
NSLog(#"current queue:%p current thread:%#",dispatch_get_current_queue(),[NSThread currentThread]);
Make sure that you write NSLog in the block that performs on your queue and not in the enumerateGroupsWithTypes:usingBlock:failureBlock:
Also you can try to create your queue like this
dispatch_queue_create("label", DISPATCH_QUEUE_SERIAL);
but I don't think that will change anything
EDIT:
By the way, method
enumerateGroupsWithTypes:usingBlock:failureBlock:
is asynchronous, why do you call it on another queue?
UPDATE 2:
I can suggest something like this:
dispatch_async(queue, ^{
NSLog(#"queue");
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER, *pmutex = &mutex;
pthread_mutex_lock(pmutex);
ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
NSLog(#"block");
if (group) {
[groups addObject:group];
} else {
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
dispatch_async(dispatch_get_current_queue(), ^{
pthread_mutex_unlock(pmutex);
});
}
NSLog(#"block end");
};
[assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:listGroupBlock failureBlock:failureBlock];
pthread_mutex_lock(pmutex);
pthread_mutex_unlock(pmutex);
pthread_mutex_destroy(pmutex);
NSLog(#"queue end");
});
I hit an issue like this, and the answer for me was to realize that asynchronous calls from a method on the serialized queue goes to another queue for processing -- one that is not serialized.
So you have to wrap all the calls inside the main method with explicit dispatch_async(serializedQueue, ^{}) to ensure that everything is done in the correct order...
Using Swift and semaphores to illustrate an approach to serialization:
Given: a class with an asynchronous ‘run’ method that will be run on multiple objects at once, and the objective is that each not run until the one before it completes.
The issue is that the run method allocates a lot of memory and uses a lot of system resources that can cause memory pressure among other issues if too many are run at once.
So the idea is: if a serial queue is used then only one will run at a time, one after the other.
Create a serial queue in the global space by the class:
let serialGeneratorQueue: DispatchQueue = DispatchQueue(label: "com.limit-point.serialGeneratorQueue", autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem)
class Generator {
func run() {
asynchronous_method()
}
func start() {
serialGeneratorQueue.async {
self.run()
}
}
func completed() {
// to be called by the asynchronous_method() when done
}
}
The ‘run’ method of this class for which very many objects will be created and run will be processed on the serial queue:
serialGeneratorQueue.async {
self.run()
}
In this case an autoreleaseFrequency is .workItem to clean up memory after each run.
The run method is of some general form:
func run() {
asynchronous_method()
}
The problem with this: the run method exits before the asynchronous_method completes, and the next run method in the queue will run, etc. So the objective is not being achieved because each asynchronous_method is running in parallel, not serially after all.
Use a semaphore to fix. In the class declare
let running = DispatchSemaphore(value: 0)
Now the asynchronous_method completes it calls the ‘completed’ method:
func completed() {
// some cleanup work etc.
}
The semaphore can be used to serialized the chain of asynchronous_method’s by add ‘running.wait()’ to the ‘run’ method:
func run() {
asynchronous_method()
running.wait()
}
And then in the completed() method add ‘running.signal()’
func completed() {
// some cleanup work etc.
running.signal()
}
The running.wait() in ‘run’ will prevent it from exiting until signaled by the completed method using running.signal(), which in turn prevents the serial queue from starting the next run method in the queue. This way the chain of asynchronous methods will indeed be run serially.
So now the class is of the form:
class Generator {
let running = DispatchSemaphore(value: 0)
func run() {
asynchronous_method()
running.wait()
}
func start() {
serialGeneratorQueue.async {
self.run()
}
}
func completed() {
// to be called by the asynchronous_method() when done
running.signal()
}
}
I thought a serial queue would wait [until] the first block is done ...
It does. But your first block simply calls enumerateGroupsWithTypes and the documentation warns us that the method runs asynchronously:
This method is asynchronous. When groups are enumerated, the user may be asked to confirm the application's access to the data; the method, though, returns immediately.
(FWIW, whenever you see a method that has a block/closure parameter, that’s a red flag that the method is likely performing something asynchronously. You can always refer to the relevant method’s documentation and confirm, like we have here.)
So, bottom line, your queue is serial, but it is only sequentially launching a series of asynchronous tasks, but obviously not waiting for those asynchronous tasks to finish, defeating the intent of the serial queue.
So, if you really need to have each tasks wait for the prior asynchronous task, there are a number of traditional solutions to this problem:
Use recursive pattern. I.e., write a rendition of processImage that takes an array of images to process and:
check to see if there are any images to process;
process first image; and
when done (i.e. in the completion handler block), remove the first image from the array and then call processImage again.
Rather than dispatch queues, consider using operation queues. Then you can implement your task as an “asynchronous” NSOperation subclass. This is a very elegant way of wrapping an asynchronous task This is illustrated in https://stackoverflow.com/a/21205992/1271826.
You can use semaphores to make this asynchronous task behave synchronously. This is also illustrated in https://stackoverflow.com/a/21205992/1271826.
Option 1 is the simplest, option 2 is the most elegant, and option 3 is a fragile solution that should be avoided if you can.
You might have more than one object, each with its own serial queue. Tasks dispatched to any single serial queue are performed serially, but tasks dispatched to different serial queues will absolutely be interleaved.
Another simple bug would be to create not a serial queue, but a concurrent queue...

Resources