Can I use a continuous background thread to update the iPhone UI without using NSTimer? - iphone

Let's say that if I read from www.example.com/number, I get a random number. In my iPhone app, I want to be able to continuously read from that address and display the new number on the screen after each request is finished. Let's also assume that I want this process to start as soon as the view loads. Lastly, as a side-note, I'm using ASIHTTPRequest to simplify the web requests.
Approach 1: In my viewDidLoad method I could synchronously read from the URL in a loop (execution will not continue until I get a response from the HTTP request). Pros: the requests are serial and I have full control to respond to each one. Cons: the UI never gets updated because I never exit the function and give control back to the run time loop. Clearly, this is not a good solution.
Approach 2: In my viewDidLoad method I create a timer which calls a fetchURL function once per second. Pros: each request is in a separate thread, and the UI updates after each request is finished. Cons: the requests are in separate threads, and cannot be controlled well. For example, if there is a connection timeout on the first request, I want to be able to display an error popup, and not have any further requests happen until settings are changed. However, with this approach, if it takes 3 seconds to timeout, two additional requests will have already been started in that time. If I just slow down the timer, then data comes in too slowly when the connection is working well.
It seems like there should be some approach which would merge the benefits of the first two approaches I mentioned. I would like a way that I could decide whether on not to send the next request based on the result of the previous request.
Approach 3: I considered using a timer which fires more quickly (say every .25 seconds), but have the timer's function check a flag to see what to do next. So, if the previous request has finished, it sends a new request (unless there was an error). Otherwise, if the previous request has not finished, the timer's function returns without sending a new request. By firing this timer more quickly, you would get better response time, but the flag would let me get the synchronization I wanted.
It seems like Approach 3 would do what I want, but it also seems a little forced. Does anyone have a suggestion for a better approach to this, or is something like Approach 3 the best way to do it?

You could do this using GCD with less code and using fewer resources. This is how you could do it:
In viewDidLoad call a block asynchronously (using dispatch_async) that does the following:
Load the data with a synchronous call and handle timeouts if it failed.
If successful, inform the main thread to update the UI.
Queue a new block to run after a delay that does the same thing (using dispatch_after).
To call back to the main thread from another thread I can think of these methods:
If you want to update a custom view, you can set setNeedsDisplay from your block
Otherwise, you could queue a block on what's called "main queue", which is a queue running on the main thread. You get this queue by calling dispatch_get_main_queue. and then treat it like any other queue (for example you can add your block by calling dispatch_async).
If you don't want to use blocks you can use the NSObject's performSelectorOnMainThread:withObject:waitUntilDone: method.
See GCD Reference for more details.
That said, you should never keep performing small requests so frequently (unless for specific tasks like fetching game data or something). It will severely reduce battery life by keeping antenna from sleeping.

I believe an NSOperation is what you need. Use the number 1 solution above, but place the code in your NSOperation's main method. Something like this:
The .h file
#interface MyRandomNumberFetcher : NSOperation {
}
#end
The .m file
#implementation MyRandomNumberFetcher
- (void) main {
// This is where you start the web service calls.
}
#end
I'd also recommend adding a reference to the UI controller so your operation queue class can call it back when it's appropriate.

Here's another suggestion. Create an NSOperationQueue that will run your requests on a different thread. If you find you need to refresh the UI call performSelectorOnMainThread. When the request completes create another request and add it to the queue. Set the queue to run only one action at a time.
This way you'll never have two requests running at the same time.

Related

Multithreading: best method for lossy thread notifications in Swift?

I have a high-priority audio thread that runs periodically and should do minimal synchronization.
Sometimes the main thread needs to ensure that at least one audio cycle has passed and certain parameters have been picked up, before sending the next batch of parameters. For example, when disabling an audio node the main thread needs to wait until the next cycle when the disabling command is picked up and the node shuts itself down.
At times it is important for the main thread to wait until the command is fully executed, but other times it's not important, so nobody might be listening to the sync event. Hence the "lossy" scenario.
So what is the best way of notifying other threads about an event with minimal overhead and possibly in a "lossy" way?
Can't think of ways of using a semaphore for this task. Are there any canonical ways of achieving this? Looks like Java's notifyAll() works precisely this way, if so, what synchronization mechanism is used behind notifyAll()?
Edit: been thinking, is there such a thing as "send me a semaphore in a queue and I'll signal it"? Seems a bit too complicated but theoretically it could do the job. Any simpler tools for the same task?
As a rule, you never want to block the main thread (or, at least, for more than a few milliseconds). If the response might ever take longer than that, rather than actually waiting, we would adopt asynchronous patterns, let the main thread proceed. Sure, if you need to prevent user interaction, we’d do that, but we wouldn't block the main thread.
The key concern is that if an app blocks the main thread for too long, you have a bad UX (where the app appears to freeze) and you risk having your app killed by the watchdog process. I would therefore not advise using semaphores (or any other similar mechanisms) to have the main thread wait for something from your audio engine controller.
So, for example, let’s say the main thread wants to tell the audio engine to pause playback, but you want the UI to “wait” for it to be acknowledged and handled. Instead of actually waiting, we would set up some asynchronous pattern where the main thread notifies the audio engine that it wants it to pause, the audio controller would then notify the main thread when that request has been processed via some callback mechanism (e.g., via delegate protocol pattern, completion handler closure, etc.). If you happen to need to prevent user interaction during the intervening time, then you’d disable controller and use some UIActivityIndicatorView (i.e., a spinner) or something like that, something that would be removed when the completion handler is called.
Now, you used the term “lossy”, but that generally conveys that you don't mind the request getting lost. But I’m assuming that is not really the case. I'm assuming that you don't really want the request to be lost, but rather only that the main thread doesn't care about the response, confident that the audio controller will get to it when it can. In that case, you'd probably still give this sort of request to the audio controller a callback mechanism, but the main thread just wouldn’t avail itself of it.
Now if you have a sequence of commands that you want the audio engine to process in order, then the audio controller might have a private, internal queue for these requests, where you’d configure it to not start subsequent request(s) until the prior ones finished. The main thread shouldn't be worried about whether the required audio cycle has processed. It should just send whatever requests are appropriate and the audio controller should handle them in the desired order/timing.

what is synchronous and asynchronous in iphone and iPad?

What is synchronous and asynchronous in ios ? I am new in objective c. Which one i should use in my code while i am getting data from server. So please help me.
Thanks in advance.
You should always use asynchronous loading of network requests.
Asynchronous never block the main thread waiting for a network response.
Asynchronous can be either synchronous on a separate thread, or scheduled in the run loop of any thread.
Synchronous blocks main thread until they complete request.
For Demo code or turorial have a look into this link Asynchronous web service client using NSURLConnection and SBJSON
The majority of the time you will go for asynchronous calls for that kind of operations, otherwise you're UI will block because you are using the main thread.
Synchronous, as the name suggests the action will happen in synchronous with the run loop of your application.
To understand it better, say you have to display some data in UITableview after fetching the data from server.Imagine that the request and response from server takes like 3 seconds. When you are fetching this data synchronously from the server, your app will freeze for like 3 seconds between loading tableview and loading the data contents into that tableview
Now if you are sending your request asynchronously, your app won't freeze but it will load the tableview and tableview contents before the server can respond. In other words, your app won't wait for the 3 second of server response time.You have to take necessary delegate actions or blocks actions to check the response and reload the tabledata so that the server response is displayed in tableview.
Which method is better is pure choice what the developer wants and their app should behave but Apple documentation recommends if you are using synchronous calls do not initiate the call from current run loop.
Using asynchronous all threads are execute the operations parallel. So, Never block the main thread waiting for a network response.
Using synchronous all threads are execute the operations one by one. so, should wait until the other thread task done.
Hope It will be suitable.
Quick note based on other answers: dispatch_sync will not block the main thread unless you dispatch to the main thread.
Example:
// Block main thread because the main queue is on it.
dispatch_sync(dispatch_get_main_queue(), ^{ /*do stuff*/ });
// Block background thread.
dispatch_sync(my_work_queue, ^{ /*do stuff*/ });
A Synchronous call(blocking) is one that has to be completed before subsequent calls can be run in the same queue. It is given all of the processor time for that queue until it is complete. This makes it block the queue.
Asynchronous calls can be started in a queue, and then left running on another thread(processor time schedule), owned by that queue, while other calls are started with other threads.
It is very important to use dispatch_async for web calls because it may take time to get a result back and you want other tasks to be able to start in the queue and use it's threads. A common practice is to do web work, like downloading a file, on a custom background queue and then dispatch to the main queue when it is complete, to update the user.
There is more to this and you can read about dispatch queues from Apple, here.

Correct way to poll a webservice in an IPhone app

I am trying to determine the best strategy to poll a webservice once a minute, parse the xml returned and then update an object stored in a shared instance. This process needs to run in a separate thread, and will continue as long as the app is running.
It seems that I could put all the code to call the webservice and parse the xml into an NSOperation and add that NSOperation to an NSOperationQueue stored in the app delegate as soon as the app launches.
Is it a correct approach to use an NSTimer inside the main method of the NSOperation so that the operation will loop once a minute, indefinitely? In that scenario the NSOperation would never actually return - this seems what I want but I am not sure if this is the right way to think about it.
The problem I am trying to solve is of course extremely common, so I am trying to figure out the correct way to implement it. Any advice greatly appreciated.
The real correct way to do it is to use push notifications. If any of your users have cell plans with limited data or data charged based on usage, they will thank you for it.
But if you insist on polling, you may as well use the NSTimer directly rather than messing with a timer inside an NSOperation. This will run on the main thread, but you could have the timer callback use performSelectorInBackground:withObject: to do processing in the background. Or you could just skip the timer altogether and run the whole polling sequence on a separate NSThread, and use sleepForTimeInterval: to delay between polls.
I would highly recommend you take a look at ASIHTTPRequest. What an amazing little class, and really well documented.
Edit:
Take a look at this answer for what seems to be the optimal solution.
one approach: create a thread and use a run loop, updating or idling as appropriate. then you can perform the request from the secondary thread and post it to the rest of the app after it's been parsed/prepped.
this way offers more control over pause/resume/delays/timing, and you can easily control the number of active requests (which should be exactly zero or one).
I wouldn't use NSTimer for this problem/design. I would create NSThread from the AppDelegate when the application starts. I would lower the priority of this thread. Inside the NSThread main method is basically a loop.
-(void)main {
while(true) {
// get raw data from url
// hash the result
// compare the hash to the last time
if (currentHash != lastHash) {
// post a notification to default center with the new data
lastHash = currentHash;
}
// sleep the thread sleepForTimeInterval
}
}
Your Model object would subscribe to the notification from the thread and parse the new data and updates ivars. Your View object would listen to the Model using KVO and display any updates/changes.

what exactly NSUrlConnection ASynchronous means?

i am getting confused what is the difference between Synchronous NSUrlConnection and ASynchronous NSUrlConnection?is there Synchronous or ASynchronous? if we use detachNewThreadSelector in connectionDidFinishLoading method,is it
ASynchronous NSUrlConnection? which is the best way?any tutorial ...
Synchronous means that you trigger your NSURLConnection request and wait for it to be done.
Asynchronous means that you can trigger the request and do other stuff while NSURLConnection downloads data.
Which is "best"?
Synchronous is very straightforward: you set it up, fire it, and wait for the data to come back. But your application sits there and does nothing until all the data is downloaded, some error occurs, or the request times out. If you're dealing with anything more than a small amount of data, your user will sit there waiting, which will not make for a good user experience.
Asynchronous requires just a little more work, but your user can do other stuff while the request does its thing, which is usually preferable. You set up some delegate methods that let you keep track of data as it comes in, which is useful for tracking download progress. This approach is probably better for most usage cases.
You can do both synchronous and asynchronous requests with NSURLConnection. Apple's documentation provides a clear explanation of the two approaches and delegate methods required for the latter approach.
It seems that you're conflating synchronous/asynchronous connections and threading. In my app I used asynchronous connections as an alternative to threading.
Let's say you want to download a big file without causing the UI to freeze. You have two basic options:
Asynchronous connection. You start with + connectionWithRequest:delegate: (or one of the other non-autorelease options) and it downloads bits of the file, calling your delegate when interesting thing happen. The runloop is still going, so your UI stays responsive. Of course you have to be careful that your delegate don't go out of scope.
Synchronous. You start the connection with + sendSynchronousRequest:returningResponse:error: but the code waits until the download is complete. You'll really need to spawn a new thread (or one of the higher level threading operations that Cocoa supports) or the UI will block.
Which option is "best" or the least painful will depend on the architecture of your application and what you're trying to achieve. If you need to create a thread for a long running process anyway, you might go with the second option. In general I would say the first option is easiest.
It's all pretty well documented on Apple's Developer site.
Something which hasn't been mentioned in the other responses is the size of the request. If you're downloading a large file, for example, then using an asynchronous connection is better. Your delegate will receive blocks of data as they arrive. In comparison, the synchronous method will wait for all the data before making it available to you. The delegate can start processing the response sooner (better user experience), or save save it to a file instead of memory (better resource usage). You also have the option to stop the response without waiting for all the data.
Basically, the asynchronous method gives you more control over the connection but at the cost of complexity. The synchronous method is much simpler, but shouldn't be used on the main UI thread because it blocks.
In response to the other answers regarding the file size: I think file size doesn't matter. If the server responds really slowly and you're loading data synchronous your UI still freezes, even if you're loading a small amount of data, like 3k.
So I'd go for the asynchronous option in every situation, cause you never know what you're going to get with regards to file size, server responsiveness or network speeds.

Asynchronous vs Synchronous vs Threading in an iPhone App

I'm in the design stage for an app which will utilize a REST web service and sort of have a dilemma in as far as using asynchronous vs synchronous vs threading. Here's the scenario.
Say you have three options to drill down into, each one having its own REST-based resource. I can either lazily load each one with a synchronous request, but that'll block the UI and prevent the user from hitting a back navigation button while data is retrieved. This case applies almost anywhere except for when your application requires a login screen. I can't see any reason to use synchronous HTTP requests vs asynchronous because of that reason alone. The only time it makes sense is to have a worker thread make your synchronous request, and notify the main thread when the request is done. This will prevent the block. The question then is bench marking your code and seeing which has more overhead, a threaded synchronous request or an asynchronous request.
The problem with asynchronous requests is you need to either setup a smart notification or delegate system as you can have multiple requests for multiple resources happening at any given time. The other problem with them is if I have a class, say a singleton which is handling all of my data, I can't use asynchronous requests in a getter method. Meaning the following won't go:
- (NSArray *)users {
if(users == nil)
users = do_async_request // NO GOOD
return users;
}
whereas the following:
- (NSArray *)users {
if(users == nil)
users == do_sync_request // OK.
return users;
}
You also might have priority. What I mean by priority is if you look at Apple's Mail application on the iPhone, you'll notice they first suck down your entire POP/IMAP tree before making a second request to retrieve the first 2 lines (the default) of your message.
I suppose my question to you experts is this. When are you using asynchronous, synchronous, threads -- and when are you using either async/sync in a thread? What kind of delegation system do you have setup to know what to do when a async request completes? Are you prioritizing your async requests?
There's a gamut of solutions to this all too common problem. It's simple to hack something out. The problem is, I don't want to hack and I want to have something that's simple and easy to maintain.
I'm not discounting asynchronous delegate calls, but I usually end up using a threaded worker class with synchronous requests. I find it's easier in the long run to have a well defined, threaded API, instead of filling up your controller with code managing the state between asynchronous methods. You could even make asynchronous in your worker thread, although usually it's easier to use the synchronous methods unless they don't support a feature you need to use. Of course, all of this depends on the circumstances, I can think of many situations where simply using the asynchronous methods would be the best route.
Definitely consider NSOperationQueue if you go this route; it greatly simplifies creating multiple worker threads, and it also supports priorities and dependancies between operations. Right now there are some problems with it on 10.5, but I haven't heard of any issues on the iPhone.
An official response is that you should almost always go asynchronous and that synchronous is bad. I found ASIHTTPRequest makes asynchronous requests easy-peasy.
I don't think that there's a "right" answer. It seems that you understand the compromises involved and you just need to make your design around those.
A few extra random points: sometimes your application forces a particular approach. For example, many of the convenience (i.e., synchronous) methods won't allow authentication. For me that meant that my decision was made.
For Yummy I ended up not using threads. I made all my network calls asynchronous and I used the default XML parser (which works using call backs). Since it's all event driven and each unit is small it allows the GUI to be pretty fluid without having the complexity of threading.
I use a state machine to figure out why I'm getting a particular response, and a queue so that I only need to have a single operation "in flight" at any given time. There's a distinct order to most requests so I have no need for a priority system.
The networking code is the most complex in my app and it took a long time to get working much less robust!
I personally look at what is being done, I will ususally use an asyc request to ensure that the UI doesn't block, however, I MAY during the course of that request disable the UI of my application.
A prime example of this is in an application that I built with a "search" button. Once the search was triggered as an async request I would disable the button until the response came back, effectivly limiting the ability for the user to spawn a second asyc request.
Doing this, at least I can prevent the need for priorites, granted this only works if you can in an easy to do way, limit your users to one action at a time.
I'd recommend the asychronous way, no question. Then, load the information only when needed, and use a delegate system to give that information to the correct object.
You don't want to block the UI. Ever. And loading information asynchronously allows you better control over what's happening so you can throw up an error message if needed.
Just a thought: If you want to use the Unit Testing framework for the iPhone, you may want to have synchronous functionality, as that could make writing the tests easier.
However, some of your APIs may not work synchronously, so you need to turn them into sync tasks. Provided the code that performs the unit testing runs in its own thread, you can write a wrapper that will wait until the async task has finished.
To accomplish that, you'd use a semaphore: Your wrapper function starts the async operation and then uses the semaphore to block itself (i.e. puts itself to sleep). The callback that signals the end of the async event releases the semaphore, so that the sleeping wrapper thread can continue and return.
I would use dispatch_async with synchronous. This way, you have the advantage of no delegates/NSNotifications and it is non-blocking
- (NSArray *)users {
if(users == nil) {
users = do_sync_request();
}
return users;
}
// now when calling the users method, do this
- (NSArray *)getUsers {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *users = [self users];
dispatch_sync(dispatch_get_main_queue(), ^{
return users;
}
}
}
Why can't you use an asynchronous request like so:
- (NSArray *)users {
if(users == nil && !didLaunchRequestAlready )
users = do_async_request // Looks good to me
return users;
}
Asynchronous is absolutely the only option - the only real question is if you want to start using separate threads, or if you want to just use the asynch calls. Start there and look at managing threads if you really need to.