Select proper multithreading technique in iOS - ios

I am confused on where to use which multithreading tool in iOS for hitting services and changing UI based on service data,
firstly I got accustomed to using NSURLConnection and its delegates, used didreceiveresponse, didreceivedata etc delegates to achieve the task
secondly I learned and used GCD to hit services and update the UI from within the block code
Now I am learning to use performSelectorInBackground() to do work in background thread
Clearly confused on which tool to use where?

NSURLConnection with delegate calls is "old school" way of receiving data from remote server. Also it's not really comfortable to use with few NSURLConnection instances in a single class (UIViewController or what not). Now it's better to use sendAsynchronousRequest.. method with completion handler. You can also define on which operation queue (main for UI, or other, background one) the completion handler will be run.
GCD is good for different tasks, not only fetching remote resources with initWithContentsOfURL: methods. You can also control what type of queues will receive your blocks (concurrent, serial ,etc.)
performSelectorInBackground: is also "old school" way of performing a method in background thread. If you weren't using ARC, you'd need to setup separate autorelease pool to avoid memory leaks. It also has a limitation of not allowing to accept arbitrary number of parameters to given selector. In this case it's recommended to use dispatch_async.
There are also NSOperationQueue with NSOperation and its subclasses (NSInvocationOperation & NSBlockOperation), where you can run tasks in the background as well as get notifications on main thread about finished tasks. IMHO They are more flexible than GCD in a way that you can create your own subclasses of operations as well as define dependencies between them.

The most important thing is, that you never change UI anyway in another thread except the main thread.
I think, that all points you mentioned use the same technique in the background: GDC. But I'm not sure of that.
Anyway it doesn't matter which tool you should use in terms of threading.
It's rather a question of your purpose. If you wan't to fetch an small image or just few data you can use contentsOfURLin a performSelectorInBackground() or a GDC dispatch block.
If it's about more data and more information like progress or error handling you should stick with *NSURLConnection`.

I suggest using GCD in all cases. Other techniques are still around but mainly for backward compatibility.
GCD is better for 3 reasons (at least):
It's extremely easy to use and the code remains very readable because of the use of blocks
It is lower level than things like NSOperation so it is much faster when you need high performance multi threading
It's lightweight and non-intrusive so your code doesn't have to change substantially when you want to add thread management in the middle of a method.

Related

How to execute all methods of an object in a certain queue in ios

For my ios app I am using the main queue and root queue. I have several objects and I want their mehtods to run in the root queue.
So far, what I have been doing is add a dispatch_async for each time I call one of those methods which will ultimately become very troublesome when I will use more queues and want to go back to main queue.
What I am looking for is way to assign objects to the root queue so that their methods are executed in the roof queue. What I mean is I am looking for sth. like this: [[TestClass alloc] initInQueue:testQueue];
It is possible to create this in a manner similar to KVO. You could swizzle all your methods to wrap them into dispatch_* calls, but I would strongly discourage it. The level of magic is too high, and you will almost certainly tie yourself up in knots. Moreover, you can't wrap an arbitrary method in dispatch_async since you can't have a return result from that. But you also can't wrap arbitrary methods in dispatch_sync because you would likely deadlock. The problems of solving the general case will quickly spiral out of control in my opinion.
What you should be asking instead is whether your queue architecture is correct. Do you really need to keep calling so many small methods on other queues? In many cases it is better to encapsulate full work units (i.e. a coherent sequence of operations that take an input and generate a final result) rather than individual method calls. (Once you think in work units, NSOperation suddenly gets a lot more useful.) While it is occasionally useful to wrap an accessor into a queue for thread-safety, this is not a general solution to concurrency.
While there are advantages to getting off of the main queue, this advice shouldn't be over-applied. You can do reasonable amounts of work on the main queue without any problems. We built single-threaded Cocoa apps on computers less powerful than iPhones long before GCD. (The iPhone is probably more powerful than my old PowerBooks and might be more powerful than my original MacBook.) I'm not discouraging queues here, just make sure you're doing it for the right reasons and don't overcomplicate things.
But if you really need to move the work, then I would recommend just being explicit with dispatch_ calls in the method itself. It's a little more typing, but it's much clearer and less error-prone.

Why use GCD and blocks for HTTP downloads?

In a job interview, I was asked why I should use blocks and GCD instead of NSURLConnection in order to download files asyncronously. After some research I haven't found a good reason to do that. I have multiple apps where I use just NSURLConnection just fine for multiple simultaneous downloads. Is their question attempting to ascertain whether I'm conforming to whatever is trendy (GCD, blocks) or is there any actual, substantial advantage to doing async fetches in this way?
Thanks.
In iOS 7, you generally should not use block-based methods to download files asynchronously. In order to support background transfers, you must use NSURLSession with delegate methods, and cannot use the block-based methods. Beyond that, I'm not sure what is meant here by "instead of NSURLConnection" in any case.
If they meant sendAsynchronousRequest:queue:completionHandler: (which is NSURLConnection), it's convenient, but much less flexible and powerful than the delegate-based NSURLConnection, so the only answer I would have is "because sometimes it's more convenient, and keeps the code closer together, when you don't need much flexibility."
Unless what they actually mean is the part of GCD that really does this: Dispatch I/O. There are reasons to use that directly (particularly if you're using non-HTTP protocols, or if you're managing an HTTP server rather than a client), but they're rare, and not usually for "downloading files asynchronously." The higher level APIs are preferred in most cases.
If you were doing many, many connections, transferring a ton of data over a very fast network connection, I can perhaps see how NSURLConnection's use the runloop for I/O handling and callbacks might become problematic, if you're scheduling these NSURLConnections on the main runloop. That said, you could just as easily spool up a lower priority background thread with its own runloop to keep those operations off the main thread.
If you didn't need all the extra machinery of NSURLConnection (caching, authentication, etc), dispatch_io* is almost certainly a lower overhead mechanism for handling raw network I/O, but you would really be giving up quite a bit of functionality for what I expect, practically speaking, to be a very marginal performance improvement.
I'm not sure. Mainly because NSURLConnection's sendAsynchronousRequest method has a completion handler built into it which uses a block.
Maybe a trick question? To me, it seems like the interviewer just wanted to see if you could conclude that they both can serve the same function.
Blocks and GCD aren't specifically for downloads, but they can make downloading easier. You would have to use them in conjunction with something that did the downloading (like NSURLConnection).
The advantage of using GCD with an NSURLConnection is that you can package it together nicely and don't have to rely on spread-out delegate methods. You can limit the number of connections easily too as well as pausing and stopping connections.
My "go to" set up for complex networking is to use an NSOperationQueue and NSOperation subclasses to do the work.
Each operation then uses a NSURLConnection and its delegate methods to download the data and then process it.
In a way this is already using GCD through the NSOperationQueue but I can't see a reason to use any other method combining blocks and GCD etc...
Did they give you a "correct" answer?

What is the best networking solution for a complex multithreaded app?

I have a streaming iOS app that captures video to Wowza servers.
It's a beast, and it's really finicky.
I'm grabbing configuration settings from a php script that shoots out JSON.
Now that I've implemented that, I've run into some strange threading issues. My app connects to the host, says its streaming, but never actually sends packets.
Getting rid of the remote configuration NSURLConnection (which I've made sure is properly formatted) delegate fixes the problem. So I'm thinking either some data is getting misconstrued across threads or something like that.
What will help me is knowing:
Are NSURLConnection delegate methods called on the main thread?
Will nonatomic data be vulnerable in a delegate method?
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
Have you looked at AFNetworking?
http://www.raywenderlich.com/30445/afnetworking-crash-course
https://github.com/AFNetworking/AFNetworking
It's quite robust and helps immensely with the threading, and there are several good tutorials.
Are NSURLConnection delegate methods called on the main thread?
Yes, on request completion it gives a call back on the main thread if you started it on the main thread.
Will nonatomic data be vulnerable in a delegate method?
Generally collection values (like array) are vulnerable with multiple threads; the rest shouldn't create anything other than a race problem.
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
I feel it's better to use GCD for handling your threads, and asynchronous retrieval using NSURLConnection should be helpful. There are few network libraries available to do the boilerplate code for you, such as AFNetworking, and ASIHTTPRequest (although that is a bit old).
Are NSURLConnection delegate methods called on the main thread?
Delegate methods can be executed on a NSOperationQueue or a thread. If you not explicitly schedule the connection, it will use the thread where it receives the start message. This can be the main thread, but it can also any other secondary thread which shall also have a run loop.
You can set the thread (indirectly) with method
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
which sets the run loop which you retrieved from the current thread. A run loop is associated to a thread in a 1:1 relation. That is, in order to set a certain thread where the delegate methods shall be executed, you need to execute on this thread, retrieve the Run Loop from the current thread and send scheduleInRunLoop:forMode: to the connection.
Setting up a dedicated secondary thread requires, that this thread will have a Run Loop. Ensuring this is not always straight forward and requires a "hack".
Alternatively, you can use method
- (void)setDelegateQueue:(NSOperationQueue *)queue
in order to set the queue where the delegate methods will be executed. Which thread will be actually used for executing the delegates is then undetermined.
You must not use both methods - so schedule on a thread OR a queue. Please consult the documentation for more information.
Will nonatomic data be vulnerable in a delegate method?
You should always synchronize access to shared resources - even for integers. On certain multiprocessor systems it is not even guaranteed that accesses to a shared integer is safe. You will have to use memory barriers on both threads in order to guarantee that.
You might utilize serial queues (either NSOperationQueue or dispatch queue) to guarantee safe access to shared resources.
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
Utilize queues, as mentioned, then you don't have to deal with threads. "Grabbing data" is not only a threading problem ;)
If you prefer a more specific answer you would need to describe your problem in more detail.
To answer your first question: The delegate methods are called on the thread that started the asynchronous load operation for the associated NSURLConnection object.

What I should use for parallelisation of frequent HTTP requests to the REST server in iOS application: GCD or NSThread?

I'm developing an application which must extract new messages for user from the server. I have implemented this as a timer which fires every 2 seconds and call a selector which is a method that implement HTTP request and server respond processing. So I think it is quite a bad idea to do this in a main thread.I have no experience with multithreading in iOS. So I want to know what fits well for parallelizing of this task: GCD or NSThread?
You should work as far up the API stack as possible. That way you can concentrate on programming functionality and not managing threads. GCD uses threads that the system has gotten going anyway and its much more efficient than managing your own code. Its even better to aim to encapsulate your networking into NSOperations that can then be put on an NSOperationQueue and these will be executed on one or more background threads, whatever the system deems is a good number for the current power status and other things like that.
The benefit of NSOperation over a pure GCD approach is that operations can be cancelled. Once a block is committed to GCD it has to run no matter what.
If you want to encapsulate your HTTP requests in NSOperations you might be interested to know that someone has already done this for you. AFNetworking is one of the most widely regarded iOS networking stacks and uses NSOperations as its base to build on and as such is very easily multi threaded.
A good idea would be to try and encapsulate your parsing code into an NSOperation and then as your network request operations return you can create parsing operation instances and put them on another queue for processing in the background.

iOS. Do NSURLConnection and UIView's setNeedsDisplay rely on GCD for asynchronous behavior?

I am doing a lot of GCD and asynchronous rendering and data retrieval work lately and I really need to nail the mental model about how asynchronous is done.
I want to focus on setNeedsDisplay and the NSURLConnectionDelegate suite of methods.
Is it correct to call setNeedsDisplay asynchronous? I often call it via dispatch_async(dispatch_get_main_queue(), ^{}) which confuses me.
The NSURLConnectionDelegate callbacks are described as asynchronous but are they not actually concurrently run on the main thread/runloop. I am a but fuzzy on the distinction here.
More generally in the modern iOS era of GCD what is the best practice for making GCD and these methods play nice together. I'm just looking for general guidelines here since I use them regularly and am just trying not to get myself in trouble.
Cheers,
Doug
No, you generally don't call setNeedsDisplay asynchronously. But if you're invoking this from a queue other than the main queue (which I would guess you are), then you should note that you never should do UI updates from background queues. You always run those from the main queue. So, this looks like the very typical pattern of dispatching a UI update from a background queue to the main queue.
NSURLConnection is described as asynchronous because when you invoke it, unless you used sendSynchronousRequest, your app immediately returns while the connection progresses. The fact that the delegate events are on the main queue is not incompatible with the notion that the connection, itself, is asynchronous. Personally, I would have thought it bad form if I can some delegate methods that were not being called from the same queue from which the process was initiated, unless that was fairly explicit via the interface.
To the question of your question's title, whether NSURLConnection uses GCD internally, versus another concurrency technology (NSOperationQueue, threads, etc.), that's an internal implementation issue that we, as application developers, don't generally worry about.
To your final, follow-up question regarding guidelines, I'd volunteer the general rule I alluded to above. Namely, all time consuming processes that would block your user interface should be dispatched to background queue, but any subsequent UI updates required by the background queue should be dispatched back to the main queue. That's the most general rule of thumb I can think of that encapsulates why we generally do concurrent programming and how to do so properly.

Resources