In my use case, I have a list and with every cell, there is a button to download a particular document. From the listing, they can click on any number of those buttons and the document has to be downloaded in the background but in a serial fashion. We will have to show some animation while downloading a particular cell document.
I've tried concurrent way and it's working fine but our main application is not able to handle such requests. So, we need to call those APIs sequential. Please let me know how we can do that.
Any help will be highly appreciated.
Related
I'm stuck between two ways of developing my application and am not sure which is best. I was hoping that somebody with a bit more experience or more understanding of Parse could help me.
I am building an iOS app with Swift and using Parse for my back-end. I really enjoy Parse and it's going well.
My question: Say I'm loading a new view. The view is driven by a Parse object, meaning I am setting up Labels, tables, buttons, etc. with data from the object. I load the object in the page load. In this scenario, should I be using the findObjectInBackgroundWithBlock() method? Or should I just be retrieving it, and not moving forward until I do?
Should I just be doing things in the background when the results do not drive the immediate next steps in my code? I am hoping this makes sense. I am running into an issue where if I find an object in the background, then I can't set a label on my view with data from that object until it is found and I have to set it inside the block.
Doesn't this kind of defeat the purpose of finding the data in the background?
The purpose of find data in background is not to block the thread. As I understood you, you have to wait for parse to finish getting all the informations, because you have to create your interface with these informations.
So what I would recommend is that you let the user wait, until the interface is ready. For example with a wait-screen or something like that. Or you block some elements which take some time to load. For example a large tableview takes quite some time to load from parse. Especially if your internetconnection isn't that good.
So you should use findObjectInBackgroundWithBlock whenever possible but only allow the user to access the view, after you've loaded all necessary data to create your view.
What you also could do is do an initial access to parse. So that you set everything up at app-start. That way, you don't have to bother the user later and the user has to wait only one time at the start of your application(or If he wants to reload the tableview. for example)
I think this is a fairly simple question...but we'll see about that.
My setup:
Xcode: 6.3.2;
Parse: 1.7.4;
Language: Obj-C
I have a bunch of PFObjects that are displayed in a TableView and within each Cell there is a button that the use can tap to pin that individual PFObject to localDatastore, so if they were to lose WiFi later on he/she could still access that object and view its contents.
What I would like to do is display a UIProgressView/UIProgressBar to monitor the progress of the object being pinned (some of my objects contain large files that may take up to 30 seconds to pin). This way the user knows for sure that the object has been saved completely and there is smaller chance they will assume the object save immediately and turned off WiFi or something else happens to jeopardize his/her internet connection.
Is there straightforward way to do this with Parse??
Negative.
PFObject currently doesn't have a 'save' with a progress block like a PFFile does (https://parse.com/docs/ios/api/Classes/PFFile.html#//api/name/saveInBackgroundWithProgressBlock:). See SDK reference here for future references. This is a great resource I suggest you save it to your bookmarks, not specifically the PFObject page but the SDK API reference in general: https://parse.com/docs/ios/api/Classes/PFObject.html
There are ways to do this, mostly personal preference, however its just like any other async call, you will have to populate a progress HUD yourself, since its not API friendly yet. This is a fairly simple process to start yourself, and as a developer you should learn how to do this anyways, you learn a lot about network calls and how tasks operate on threads etc. In the meantime, as a quick fix you could simply just populate a UIActivityIndicator collectively with pinInBackgroundWithBlock: and set userInteractionEnabled to No for whatever views you want simply as a visual aide on the users end, and then hide it when complete and set userInteractionEnabled back to Yes.
I am Not Using: ASIHTTPRequest, AFNetworking, RestKit.
I have multiple images/files to be downloaded via Asynchronous call to web service for downloading.
I am showing SVProgressHUD (Activity Indicator, NOT Bar) during the download process.
Till this point, everything works fine.
Now, my client wants me to show the single ProgressBar on the view for file(s) being downloaded, so as to make user aware about the approximate time it would take.
Problem: How can I get consolidated time/size for the files being downloaded Asynchronously.
I am open for using any API that serves the purpose. I hope I am making sense, here.
Hard Time. Any Hints?
Take a look at NSProgress, it's not a UIKit class but will allow you to crate multiple instances of NSProgress (one for each activity) and then get a combined progress value which you can hook up to your UI.
There a good write up about it here with examples:
http://oleb.net/blog/2014/03/nsprogress/
You basically use KVO to read the progress value and then update your UI element i.e. progress bar.
One option is to get length of all files with "head" request, then just calculate it yourself:
amount of data downloaded/total-data-length.
This post will help you to get total content length: Objective-c Check file size from URL without downloading
Other option - start downloading each file in separate thread and use shared variable to get consolidated time.
Hope this helps.
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.
I am making e-NewsPaper app for both iphone and ipad which supported both for iOS 6 and iOS7.
In the app , there will be 1 week of news to display(in 1st view) and each news contains 10 to 15 news pages and 30 to 40 articles for those pages (in the 2nd view). So each news contains 10 to 15 images and 30 to 40 xml articles (i.e to be parsed and displyed in webview).
I am using ASIHttpRequest for requesting and downloading images and xml and NSXMLParser for xml parsing. I am using UICollectionView for displaying News list in cells.
There is multiple news downloading in asynchronous way. Also user can play - pause -resume (start - stop -cancel) this downloading in between by clicking button on each cell. There will be also one progressview to indicate downloading progress on each cell.
I am doing following tasks/steps to download and display news and its articles ;
1) Call PHP webservice and parse its JSON response and get News Paper list i.e going to display in collectionview of 1st veiw.
2) On clicking of any News Paper (i.e on collectioview cell), parsing will be started for that news's xml file.
3) Then with parsing of that file, the images and xml files are going downloaded in document directory.
I am able to download single as well as multiple news (with their images and xmls) but could not be able to identify , manage or track which news's images and xmls are downloading or downloaded among multiple news due to it is asynchronous.
I need to track , identify each news's request uniquely (with its images and xmls downloading process) so that i can play-pause downloading.
I have searched a lot but could not be able to handle this.
Please help me...
Thanks...
I'v never worked with ASIHttpRequest, im used to AFNetworking. Either way, i just checked ASIHttpRequest documentation and they seem to use NSOperations just like AFNetworking for handling requests. Maybe you could map your operations with any id you have in your models. If this works for you then it will be very easy to cancel, pause, resume any operation, just looked them up where you stored them and perform tasks over them.
Hope it helps.