Load data from server quickly iOS - ios

I am working on a shopping app where I use web services to fetch data i.e. product list etc. But it takes too much time to load and thus makes my app really slow.
Is there any solution to this problem?
below is the code I've tried to get Product List.
NSURL * Url=[NSURL URLWithString:#"URL/api/product"];
NSData * Data=[NSData dataWithContentsOfURL:Url];
NSString *str=[[NSString alloc]initWithData:Data encoding:NSUTF8StringEncoding];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[strinng dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:nil];
cannot put JSON response because it's too much.

There is no RIGHT or WRONG way way for this. But there are some points which we can consider for fast data loading. I can mention these points and there can be many other points as well:
Use AFNetworking (for objective c) or Alamofire (for swift), for calling web services and getting response.
Don't do too much things in viewDidLoad. Try to do as less as operations.
You can call web service in viewDidLoad or in viewWillAppear(it will get called every time you visit screen)
After getting response update UI on main thread. Refer this post.
If you want to show images from URL's, load it asynchronously. You can use third party library like SDWebImage Or else use extensions provided in AFNetworking and Alamofire
If you want to show list of products in list, use Load More functionality. for this purpose your API's should be smart enough which are implemented using pagination.
Use UITableView or UICollectionView for showing reusable components.
Till now I can highlight these points. If I found anything else, I will update my answer.

It will be better if you show what you did for that, but according to your requirement i will suggest you,
Use AFNetworking to communicate with server, it is little bit faster.
if you send request to server in new ViewController, make sure you are going to send request in viewWillAppear.
Try to avoid get too much data at the same time.
Try to use Asynchronous request means that it will not wait. You use Asynchronous means that it will not wait. means the thread that initiated that operation will wait for the task to finish before continuing.

Just use NSURLSession. It is good API from Apple. Just remember to use dispatch grand central get mainQueue in the completion block to update any UI.

Start loading the data from API when the App Launches (AppDelegate)and store the response data in a model. This way the time lag would be reduced. Also you can try saving the response into CoreData and when the view is loaded you can refresh the data.
Hope this helps.

Nothing can be done on your side to speed up the process when the data you receive is in abundant.
You should split your APIs, probably, one API will give you the list
of products.
Make an API in way to send only request number of products and the
number of products should be based on your phone screen resolution
and number of products that can be shown there. For example, it
could be 4 on iPhone 4 whereas 6 on iPhone 6. On scrolling call that API again to receive another 4 or 6 products.
On clicking a particular product, use another API to get its
contents.

Related

Fire and forget URL download for iOS

Problem
I'm currently grabbing weather forecast information with [NSData dataWithContentsOfURL: url]. The problem with this is that if there are errors during the URL fetch, I just get back a nil.
An alternative to the method [NSData dataWithContentsOfURL:options:error:] will provide error info to me, but what my calling function wants is the data, not a possible error that it must diagnose and deal with.
Requirements
What I'd like is a single function that a client can call to grab a URL that "absolutely will not stop" until the URL has been loaded.
I don't want the function's clients to need to think about:
Timeouts.
Internet connections being unavailable or not.
The device being locked or the app moving in to the background.
The actual site in question being down.
Other sources of error.
Other design objectives
The function should treat the device and remote site nicely – it should not swamp it with requests resends that will certainly fail, for example.
The caller should be able to abort the attempt if it desires, so it'll want to have a handle to the request allowing it to kill it off.
The function should be asynchronous, taking a block to handle the result when it eventually arrives.
For extra marks a method for the calling function to be sent error diagnostics would be nice. Again, I think a block would work nicely for this. The needn't do anything about the error, because the function isn't going to give up, but it can use it to provide useful feedback to a user. For example, to allay their concerns, or prompt them to take remedial action (turn networking back on, for example).
Possible interface
So the a client call to the function might go like this:
_currentGrabber = [TenaciousURLGrabber
grabberForURL: myURL
withCompletionAndDiagnosticsHandler:
^(NSData* finalData, ErrorObject *error){
if(data)
{
// Update my UI using data.
}
else
{
// Update my UI to show `[error localisedError];`
}
}];
If the client gets bored or decides that the fetch isn't worth it any more, it can do:
[_currentGrabber invalidate];
Implementation thoughts.
It'd be great if this pretty much already exists. Otherwise, I'm interested in suggestions on implementing this functionality.
I should probably be making use of NSURLSession instead of the older NSURLConnection. The possibility of background (out of process) downloads looks useful? Any tips beyond this?
The function should use SCNetworkReachability as demonstrated in the Reachability sample application following failure to determine when its worth a retry attempt.

Using NSURLSession to download a lot of images

I have created a simple testing app to learn how to use NSURLSession. This App has to download images from a webservice and present them into a UITableView.
I've already written the first part of the App that reads a list of images urls from the web service, now, I want to display this list.
My doubt is:
given that the list of images could be a really long list, is it ok to create a NSURLSessionDownloadTask for each image?
I thought to create the session in the cellForRowAtIndexPath function and store the NSURLSessions in a NSDictionary using as key the IndexPath of the cell (and probably relying on NSURLCache to avoid to download the same images more than once).
Other solutions:
I can see three more solutions:
Using GCD with dispatch_async
Subclassing NSOperation and essentially store an NSOperation for any image I need to download.
Using a third party library like AFNetwork... but since it is a learning purpose app I prefer to go completely with my code
.
If the multiple NSURLSession isn't a good solution, I'd choose one of those options.
What do you think about this approach?
NSURLSessionTask is fine for a large number of downloads. One advantage of it over some of the other methods you mentioned is that downloads can be cancelled or paused. It also correctly implements concurrency for network operations, which is more difficult than many cats on the internet will lead you to believe (if you don't believe me, view the eskimo's 2010 WWDC session and sample code. NSOperation for network connections is not trivial).
NSURLSessionTask and friends are designed for exactly the kinds of problems you are trying to solve, and it's very well tested.
For a tableview, start the task in tableView:willDisplayCell:forRowAtIndexPath: and cancel (or pause) a task in tableView:didEndDisplayingCell:forRowAtIndexPath:. That will limit the active downloads to the currently visible cells.
Suggestion:
I also came across a similar situation were I need to download about 2000 Image files and 100 Video files. For that purpose I implemented a custom download manager using NSOperationQueue and blocks.
I have added this library to GitHub, please feel free to check the implementation.
IMO whilst it is ok to create an NSURLSessionTask for each image a standard first in first out implementation will cause problems when scrolling through your cells. The reason for this is that downloads will be queued on your NSURLSession and tasks will be executed in the order they've been added to the queue, in other words in a FIFO manner. Imagine a scenario where you've scrolled through a vast number of cells and you have to wait for all downloads to complete in order. You would not only have to wait a long time, you would be making unnecessary network requests for image assets that may no longer be relevant to your user.
Nick Lockwood created a great NSOperationQueue subclass called NSOperationStack that reverses the order of operations so that the the last operation is executed first (LIFO). IMO for a large number of downloads a LIFO implementation is a must.
NSOsperationStack is available here
If you combine this with an implementation that uses cellForRowAtIndexPath to initiate and NSURLCache to store downloads, you should end up with a very streamlined and efficient solution.
I would use (or at least take a look at) SDWebImage's SDWebImageManager.
Besides downloading you can set priority and continue in the background options which I think you'll want to have.

Using AFNetworking to queue many JSON requests and save their responses

I'm new to AFNetworking and I'm interested in using it to handle a few dozen JSON requests (for example, using a web service's API that responds with JSON) for my application, but I'm having some trouble understanding how I should do this.
Could anyone offer some insight on how I'd go about accomplishing this? Like I said, I'm new to the library so an explanation would be greatly appreciated if you explain with code.
For a more specific example as to what I'm trying to do, here's the Clear Read API I'm using, where you pass the URL as a parameter in the URL and are returned a JSON response (the API extracts the article from a URL, removing the other bloat).
Example URL: http://api.thequeue.org/v1/clear?url=http://blogs.balsamiq.com/product/2012/02/27/uxstackexchange/&format=json
I'll be taking a few dozen URLs and running them all through that service and wish to save the results.
I was previously doing this with NSURLConnection in a for loop, firing off several dozen NSURLConnections, which was causing my data to be quite messed up by the end, with timeouts and whatnot from so many going at once.
I understand that it would be better to do only a few at a time, and AFNetworking seems perfect for this kind of problem, but I'm really just confused how I'd use it/subclass it or whatever.
I'd recommend starting with their Getting Started guide.
There's not much too it, really: build an AFJSONRequestOperation for each call to the API you want to make, and in the success callback, handle the deserialized JSON appropriately. If you have a bunch of calls to make, use AFHTTPClient to a) simply some of the repetitive work of building those operations, and b) use the client's operation queue to batch them all up. You can then throttle the number of requests in flight at once with the queue's setMaxConcurrentOperationCount: method.

iOS - Progressive Download Indicator While Downloading Files

So this question has been asked a bunch of times, but all the answers are to us ASIHTTP library which is no longer supported.
So I was hoping someone could steer me in the right direction.
I download files (images / videos) in my app using NSData and was wondering how to go about displaying a progress bar/indicator that actually tracks the progress of the download (i.e. 20%, 30% etc etc)
Are there any built-in classes that allow file downloads to be tracked with progress updates?
If you have an NSURLConnection delegate then:
the NSURLResponse you receive to connection:didReceiveResponse: will be of type NSHTTPURLResponse. If you access [[response allHeaderFields] valueForKey:#"Content-Length"] you'll get a string with the length of the data you're expecting to receive;
subsequently through the accumulation of data via connection:didReceiveData: you'll know how much data has been returned.
Since you know how many bytes you've received and how many you're expecting you'll be able to work out the percentage pretty easily.
There are several replacement options for ASIHTTP. The leading one is AFNetworking. It includes support for a progress bar for downloads.
Check out ASIHTTPRequest . It is awesome an will do this any many more wonderous things.
http://allseeing-i.com/ASIHTTPRequest/

iOS - run multiple async requests at the same time

I'm a beginning iOS developer and in my first app I want to load data for my view controller, but the problem is that the data comes over from three different web services. I use NSMutableRequest in an attempt to implement this functionality.
What I want to do is issue three requests to load data at the same time and when the last one finishes, remove the activity indicator.
I tried using an NSOperationQueue, but with async it doesn't execute the didReceiveData or didFailWithError methods. Please do comment if you need more detail or explanation (my English is not very good).
Thanks.
I would look at GCD, and create 1 synchronous request that contains your 3 asynchronous requests to your web services. This way you let GCD do the work of waiting for each of the async operations to complete. There are a few really good videos on itunes from WWDC (Apple's developer conference) that are incredibly informative with regard to GCD.

Resources