I apologize if this is a duplicate post on this forum (issues w the malware warning may have caused a double-post).
Ok, here we go:
I'm trying to figure out how to incorporate a download manager into my app similar to the one found in iDownloader and DownloadLite.
Essentially, I need a way to queue downloads and have the d/l status appear in a tableview showing separate progress indicators. Although it would be nice, I don't need a way to pause/resume these downloads. I do, however, need a way to start these downloads from one viewcontroller and have them continue even if I navigate away from this controller. That's the part I really have no clue how to do.
If any one can point me in the direction of a tutorial or something that would be great. I'm not a copy/paste programmer. I'd much rather learn how to do it.
Oh, I forgot to mention... I'd like to do this with NSOPERATIONQUEUE and NSURLCONNECTION (not ASIHTTPRequest). I don't need/want the extra overhead. Such a Diva! Ha Ha Ha.
Any help is MUCH APPRECIATED!!!
- Paradox927
P.S. I have a similar post on RWForums. If I get any solutions, I will update both threads. Hopefully, this is ok.
I apologize if this is a duplicate post on this forum (issues w the malware warning may have caused a double-post).
Ok, here we go:
I'm trying to figure out how to incorporate a download manager into my app similar to the one found in iDownloader and DownloadLite.
Essentially, I need a way to queue downloads and have the d/l status appear in a tableview showing separate progress indicators. Although it would be nice, I don't need a way to pause/resume these downloads. I do, however, need a way to start these downloads from one viewcontroller and have them continue even if I navigate away from this controller. That's the part I really have no clue how to do.
If any one can point me in the direction of a tutorial or something that would be great. I'm not a copy/paste programmer. I'd much rather learn how to do it.
Oh, I forgot to mention... I'd like to do this with NSOPERATIONQUEUE and NSURLCONNECTION (not ASIHTTPRequest). I don't need/want the extra overhead. Such a Diva! Ha Ha Ha.
Any help is MUCH APPRECIATED!!!
- Paradox927
P.S. I have a similar post on RWForums. If I get any solutions, I will update both threads. Hopefully, this is ok.
You don't need to use NSOperation. NSURLConnection is async by it's nature.
What I would suggest doing is creating a download object. Each download object would track a single download. It would set up an NSURLConnection, set itself up as the delegate, and handle the incoming data. Set up a delegate property in those download objects, and set up a protocol to notify the delegate about the status of the upload. You could pass back a percent complete, for example, and a download complete message or download failed message.
You could then write a download queue class that would maintain an array of these download objects. The download queue object would have methods to start a download, including a pointer to delegate. If the delegate pointer isn't nil, the download queue would set the delegate in the download object it creates.
You might want to include some sort of unique ID for each download, either passed in from the caller or generated by the download queue class.
If the unique ID is sent in from the caller, the view controller for your table view could use the row/section number of the entry in the table view as the ID, so it could respond to download status updates by updating a progress indicator on the cell for that row/section, if the cell is still on-screen. (The view controller would call the table view's method cellForRowAtIndexPath to see if the cell for that index path is on-screen.)
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
You don't need to use NSOperation. NSURLConnection is async by it's nature.
What I would suggest doing is creating a download object. Each download object would track a single download. It would set up an NSURLConnection, set itself up as the delegate, and handle the incoming data. Set up a delegate property in those download objects, and set up a protocol to notify the delegate about the status of the upload. You could pass back a percent complete, for example, and a download complete message or download failed message.
You could then write a download queue class that would maintain an array of these download objects. The download queue object would have methods to start a download, including a pointer to delegate. If the delegate pointer isn't nil, the download queue would set the delegate in the download object it creates.
You might want to include some sort of unique ID for each download, either passed in from the caller or generated by the download queue class.
If the unique ID is sent in from the caller, the view controller for your table view could use the row/section number of the entry in the table view as the ID, so it could respond to download status updates by updating a progress indicator on the cell for that row/section, if the cell is still on-screen. (The view controller would call the table view's method cellForRowAtIndexPath to see if the cell for that index path is on-screen.)
Thank you for the reply.
I didn't realize this could be done without using NSOperationQueue. Everything I read made some kind of referene to it. This is good news; makes it slightly less complicated now. :-)
Having said that... I'm still confused about the creation of the download queue. The download object is pretty straight forward.
Here's where I'm lost: in my tabbed-application, if I'm in viewController1 (tab 1) and I press a button that fires off the download (which basically creates the downloadObject), and then I navigate to viewController2 (tab 2) to view my current active downloads (aka my uitableview with progress indicators) how do I get access to the downloadQueue's array objects? And when setting the downloadObject's delegate, which controller becomes the delegate?
Clearly, I'm over thinking this. I have a pretty good understanding of protocols and delegates, but this shared "downloadQueue" class is just confusing me. D'oh!
To access, the download queue's download objects, you'd create a read only property in the header and redefine it as readwrite in the .m file via a class extension. The reason for making it read only is that other classes should not alter the array. I'll let Duncan answer the delegate question.
__________________
If you are looking for a quality developer, I'm your man. Give me a PM if you are interested.
To access, the download queue's download objects, you'd create a read only property in the header and redefine it as readwrite in the .m file via a class extension. The reason for making it read only is that other classes should not alter the array. I'll let Duncan answer the delegate question.
Hi, Domele.
So... would I initialize the downloadQueue in the AppDelegate or set it up as a Singleton?
I didn't realize this could be done without using NSOperationQueue. Everything I read made some kind of referene to it. This is good news; makes it slightly less complicated now. :-)
Having said that... I'm still confused about the creation of the download queue. The download object is pretty straight forward.
Here's where I'm lost: in my tabbed-application, if I'm in viewController1 (tab 1) and I press a button that fires off the download (which basically creates the downloadObject), and then I navigate to viewController2 (tab 2) to view my current active downloads (aka my uitableview with progress indicators) how do I get access to the downloadQueue's array objects? And when setting the downloadObject's delegate, which controller becomes the delegate?
Clearly, I'm over thinking this. I have a pretty good understanding of protocols and delegates, but this shared "downloadQueue" class is just confusing me. D'oh!
I didn't read your original post closely enough it seems.
If you have 2 view controllers that need to monitor your download queue, you might want to use notifications instead of delegate messages.
We wrote a download manager that does either. When you queue a download, you can provide a delegate and/or a notification message to send. If you provide a notification message, it broadcasts notifications.
In your case, you will want to provide different types of notifications. (download progress and download completed/failed messages). You could use the userInfo in the notification to provide a message type and extra data (just create a dictionary format that lets you pass different kinds of info back. have a messageType key. For message type downloadProgress, have another key progressValue which contains and NSNumber value from 0 to 1 for the percent complete. Have another messageType downloadComplete with no additional keys in the dictionary, and another message type downloadFailed, with an error message key/value pair.)
In our case, we used the URL to the file we were downloading as the notification name. In your case, you could use the index of the item in your data source, in string format. Then, when a delegate message comes in, you can use the index to find the item and update the download status, display the image, or whatever.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
this can be done with such a minimal amount of code you wouldnt believe it! just look into asihttprequest. its amazing!! i use it all the time for my new apps that include downloading.
I'm just about done implementing a fully functional solution (based on all the wonderful feedback). Since I'm already using CoreData in this app, it made a few things a little easier.
I'll post back more details once I work out all the "funny-little" details (quirks).
this can be done with such a minimal amount of code you wouldnt believe it! just look into asihttprequest. its amazing!! i use it all the time for my new apps that include downloading.
I had considered using that, but I'm such a control freak! Ha Ha! Besides... I didn't want to bring in all the extra overhead if I didn't need it.
BTW... I heard a rumor that it may be discontinued??? Is that true??? Nah... can't be. It seems so popular.