I'm working on an app that needs to be able to upload an array (can contain a mix of UIImage or a custom struct that contains a local file URL and some data). I've seen Operations and OperationQueues as a possible starting point but I don't know if I'm looking in the right direction.
Hopefully, this image can provide some clarity regarding what I need to accomplish. Basically, each ProgressViewController can have its own "uploadable" array and I also need to track the progress for each upload. I know I need to use the URLSessionDelegate methods for tracking progress, but are Operations, OperationQueues and a singleton "UploadManager" of sorts the way to go?
Thanks for your help guys!
Related
Say we have a User class with properties id: Int, name: String, imageUrl: String.
Our imaginary API stores the URL to the image. Is there a way to fetch this image once, and then reuse it in many places across the app as if it were another variable like name? I'm basically trying to be able to call user.image as a property after I fetch it.
I have no issues asynchronously fetching the image, but I can't figure out how I can only fetch it once, store it somewhere, and reuse it as a class variable (or at least something like it, just as simply), instead of fetching it every time I want to use it.
I'm sure many people deal with a similar type of situation where APIs return URLs to images. Is there an efficient way to handle this?
You could probably implement this yourself but I'd recommend Kingfisher instead. Kingfisher does exactly what you're asking for, it caches images so you only need to get them from the server once.
Me and my team are currently rookie developers in Objective-C (less than 3 months in) working on the development of a simple tab based app with network capabilities that contains a navigator controller with a table view and a corresponding detailed view in each tab. The target is iOS 4 sdk.
On the networking side, we have a single class that functions as a Singleton that processes the NSURLConnection for each one of the views in order to retrieve the data we need for each of the table views.
The functionality works fine and we can retrieve the data correctly but only if the user doesn't change views until the petition is over or the button of the same petition (example: Login button) is pressed on again. Otherwise, different mistakes can happen. For example, an error message that should only be displayed on the root view of one of the navigation controllers appears on the detailed view and vice versa.
We suspect that the issue is that we are currently handling only a single delegate on the Singleton for the "active view" and that we should change it to support a behavior based on the native Mail app in which you can change views while the data that was asked for in each one of the views keeps loading and updating correctly separately.
We have looked over stackoverflow and other websites and we haven't found a proper methodology to follow. We were considering using an NSOperationQueue and wrapping the NSURLConnections on an NSOperation, but we are not sure if that's the proper approach.
Does anyone have any suggestions on the proper way to handle multiple asynchronous NSURLConnections to update multiple views, both parent and child, almost simultaneously at the whim of the user's interaction? Ideally, we don't want to block the UI or disable the buttons as we have been recommended.
Thank you for your time!
Edit - forgot to add, one of the project restrictions set by our client is that we can only use the native iOS sdk network framework and not the ASIHTTPRequest framework or similar. At the same time, we also forgot to add that we are not uploading any information, we are only retrieving it from the WS.
One suggestion is to use NSOperations and a NSOperationsQueue. The nice thing about this arrangement is you can quickly cancel any in-process or queued work (if say the user hits the back button.
There is a project on github, NSOperation-WebFetches-MadeEasy that makes this about as painless as it can be. You incorporate one class in your classes - OperationsRunner - which comes with a "how-to-use-me" in OperationsRunner.h, and two skeleton NSOperations classes, one the subclass of another, with the subclass showing how to fetch an image.
I'm sure others will post of other solutions - its almost a problem getting started as there are a huge number of libraries and projects doing this. That said, OperationsRunner is a bit over 100 lines of code, and the operations about the same, so this is really easy to read, understand, use, and modify.
You say that your singleton has a delegate. Delegation is inappropriate when multiple objects are interested in the result. If you wish to continue using a singleton for fetching data, you must switch your pattern to be based on notifications. Your singleton will have responsibility for determining which connection corresponds to which task, and choosing an appropriate notification to be posted.
If you still need help with this, let me know, I'll try to post some sample code.
I'm just starting off on my first attempt at the MVP architecture in GWT.
My understanding is that the job of PlaceTokenizer.getPlace(String) is to take the token in the URL after the hash, parse it, and return a Place with the object to which that token refers.
In my application, I have a resource (say, a video), which I tokenize by the video's unique id. Then my getPlace method ought to take this id, and retrieve the video information from the server. Is this the right approach?
As far as how to execute this, the only way that I could figure out would be to have my RemoteService right on the PlaceTokenizer, and make the call right in that getPlace method. Something about this made me hesitate. It seems like the call would be better suited for the Activity or somewhere else.
Is this how it's done? If not, is there a better way?
Your Place doesn't need to download the video. It could just contain the video's id.
Your Activity will receive the Place, which has the video id, and now the Activity can do the downloading or whatever heavy lifting you want.
So: Your PlaceTokenizer only needs to know enough to store the video id in the Place. Let the Activity do the work after that. The only function of getPlace is to turn a String into a Place.
It helped me to mentally rename Place to PlaceTag. The place objects really do not represent places - they represent tags or pointers to places. The actual place is represented by, terribly, the Activity.
if i may help clarifying the place signification a little more. Your place object is a serializable representation of the state of your client. it will help the activity restoring the screen to its former state by containing all the information you need to build it back.
I have a few apps that I am trying to develop a reusable URL connection layer. I have done some research and am struggling between architectures. Specifically the APIs this layer utilizes.
In the past, I have used NSURLConnection and NSOperation on a separate RunLoop. This seems overkill. I've seen libraries that subclass NSURLConnection. Others have a singleton Engine object that manages all requests.
The Engine and/or NSURLConnection seem best to me. But I am asking for input before I go too far down one road. My goals would be:
Ability to cancel a request
Concurrent requests
Non-blocking
Data object of current open requests
Any direction or existing references with code samples would be greatly appreciated.
I'm not sure about a "data object of current open requests", but ASIHTTPRequest does the first three and is very easy to use.
Update
Actually, it looks like ASINetworkQueue may fulfill your last bullet point.
I personally use a singleton engine with my large Apps though it might not always be the best case. All the URL's I use require signing in first, figured it would be best if one Class handles all of the requests to prevent multiple URLS from signing into the one location.
I basically create a protocol for all my different connection classes into my singleton and pass the delegate of both the calling class and the singleton into it. If an error occurs its passed to the singleton so it can deal with it, if it completes it returns the data to the calling class.
I've not found a answer to this question anywhere, but this seems like a typical problem:
I would like to send some POST-Requests (with ASIHTTPRequest, what I already do), but if something goes wrong, ther user can decide to "Try Later", that means, the task should be put on a queue and this queue should be read next time the application starts. So, that's my question: how to "save" the queue, so that the app can read it next time it starts? Is it possible to "read" the queue and try sending this POST-Request again, let's say, 10 min later, even if the application is not running?
What kind of documentation should I read in order to be able to do this?
I would be very glad to hear any answers. Thanks in advance.
P.S.: Another Idea I have: as I just have to Upload Photos, I could have a folder with all the Photos that still need to be uploaded, and when the App starts, the app looks at this folder and try to send all the photos in this folder. Does it make sense?
My approach for this issue would be like this:
Whenever you fail to send details - write content of the array to a file using '[NSArray writeToFile:]' you can use serialization if array contain any data which is custom defined (if your array contain standard cocoa objects(NSString,NSData etc) they already implemented with serialization )
When app launches; load the content from file directly to an array object ('[NSArray arrayWithContentsOfFile:]')
then construct http request and try sending. In application the data(in your case array) is stored/serialized not the request, you need to reconstruct the http request when you want to try one more time.(don't try serializing ASIHTTPRequest, you have reconstruct it)
I'm going to assume you've already looked at NSOperationQueue and NSOperation. AFAIK there is no built-in support for serializing NSOperation, but you could very easily write your own serialization mechanism for an NSOperation subclass that you use for posting data and write the an NSOperationQueue's operations to disk if something goes wrong.
Without knowing too many details it's hard to give a precise answer. There are many ways to write data to disk and load it again later, the direction you take will be largely dependent on your situation.