I read something about multi thread access on DB but still not sure best way to do that for reading/writing in conjunction with async network download.
For instance I will have a page with images from the web, so I'm retrieving them by their URLs, using AFNetworking but I want to check first on my DB and write on it (or disk) the retrieved image for future use.
What can be the best way to do that without blocking the UI (like when scrolling)?
If I do that with a singleton that reads/writes it block the main thread.
Thanks for any tips on that.
AFNetworking is not the tool for that. Instead, you can take advantage of the built-in functionality of NSURLCache--specifically Peter Steinberger's fork of SDURLCache.
In -applicationDidFinishLaunchingWithOptions:, do NSURLCache +setSharedCache: with an instance of SDURLCache (with some amount of disk space allocated). All requests made through UIWebView (and AFNetworking, for that matter) will automatically be routed through NSURLCache before the request is made to check the cache. It's unobtrusive, drop-in, and follows cache directives correctly, and it should solve your problem quite nicely.
Related
My iOS app is somewhat similar to Facebook in the sense that it will display user generated 'posts' in a scrollable tableview, each with an image to display.
To try and avoid downloading images each time the users scrolls through the tableview, I'm using FTWCache to store each post's image data, as such:
[FTWCache setObject:loadedData forKey:[NSString stringWithFormat:#"postID%#", post.ID]];
Is this a poor practice, to lean heavily on a caching class like this? After awhile, the cache would become considerable in size, should I be flushing it every so often?
If anyone has any advice it would be much appreciated.
I'm not familiar with FTWCache but I can see that it was last maintained 3 years ago while SDWebImage or AFNetworking is maintained daily with a really big community behind it.
I'd go with AFNetworking. You shouldn't worry too much about leaning heavily on caching. That's what it's for. You could however read a bit more about how NSURLCache works and how AFNetworking is using it.
Here's the gist of it:
AFNetworking takes advantage of the caching functionality already
provided by NSURLCache and any of its subclasses. So long as your
NSURLRequest objects have the correct cache policy, and your server
response contains a valid Cache-Control header, responses will be
automatically cached for subsequent requests.
I am looking for best practices.
In my app, I send a request to my server for the URLs of the images I need to download and some meta data. I then need to store these images on disk. Once they are saved I have to update view. Storing on disk is also necessary for offline view so maybe I'll even have to store the file path to CoreData.
I think I can just use NSURLConnection to retrieve the image urls, then the images and then write them to disk. My concern is what should I do when the app is waiting for all this to occur? How do I know when to update, for example, a table? What if the user moves away and the view unloads? Just looking for advice.
Should I create a separate NSObject class to handle all this?
PS: How would I check for an existing internet connection before I do any of this anyway?
if you are already using CoreData, consider storing the images directly in the CoreData-DB. that depends on the size of the image, of course.
For synchronization of the db, this might be helpful: http://www.raywenderlich.com/15916/how-to-synchronize-core-data-with-a-web-service-part-1. They also use a separate class to handle this.
To check the internet connection, apple has a wonderful sample app:
https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html
EDIT: Oh, and NSURLConnection loads data asynchronously by default, so your app will stay responsive during data loading operations, you can handle the update-vioew-operations in the respective callback methods.
See the docs:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/
pay special attention to the difference between
sendAsynchronousRequest:queue:completionHandler: and
sendSynchronousRequest:returningResponse:error:
I have a problem regarding the best approach to make an App that has to download and show pdf's, It is fed by a JSON that has links to 147 pdf files, sized between 1 and 2 MB.
Questions:
What is the best approach to download all the files to an iPad?
Shall I use AFNetworking 2.0?
Is NSFileManager the way to save all the files?
Problems I may encounter:
With an asynchronous download, if lost connection or no more space on the iPad, what are the counter mesures?
Are there tutorials or examples that deal with this situation?
Sorry for all the questions but I'm new to this.
Best Regards.
What is the best approach to download all the files to an iPad?
This is really broad as #rmaddy suggested. Specific questions are more easily answered. There are lots of ways you could download a file via an HTTP request to your device each with pros/cons depending on your situation.
Shall I use AFNetworking 2.0?
Sure. You'll get no argument from me. This is a widely used and solid API to interface with HTTP-based resources.
Is NSFileManager the way to save all the files?
Yes. NSFileManager is the class you use to read/write files from/to your app's sandbox.
With an asynchronous download, if lost connection or no more space on the iPad, what are the counter measures?
I'm not 100% certain so I can't speak to exactly what happens in this case. AFNetworking may provide some help by writing to a temporary file during a download, etc....
Are there tutorials or examples that deal with this situation?
I have a sample project on Github that shows a table of files that you can download. You can watch the progress of your downloads, pause each request, resume and cancel as well. When you're done you can view the file you downloaded. It uses AFNetworking and might be useful to you:
https://github.com/chefnobody/StreamingDownloadTest
When downloading large files, the main counsel would be to avoid trying to load these into memory as you download them. Instead, make sure you stream them directly to persistent storage. In terms of handling space-specific errors, just make sure you check NSError objects that are returned to you in completion handlers or the appropriate delegate methods.
If using AFNetworking, you can specify the outputStream of the AFURLConnectionOperation to reference a NSOutputStream that you create, referencing some path in your persistent storage.
See Memory pressure issue while downloading multiple files using AFNetworking for example.
Alternatively, you can use NSURLSession (whether via AFNetworking or you do it yourself) and instantiate a NSURLSessionDownloadTask, which does the same sort of thing.
Google "NSURLSessionDownloadTask example" and you'll find tons of references. The block-based rendition of downloadTaskWithURL is incredibly simple. To do background downloads is a little more complicated and requires delegate-based implementation (see Downloading Files and Handling iOS Background Activity sections of URL Loading System Programming Guide: Using NSURLSession or watch the WWDC 2013 video, What’s New in Foundation Networking.)
Either way, you avoid some of the memory consumption challenges associated with downloading large files.
I have to download thousands or millions of hotposts from a web service and store them locally in core data. The json response or file is about 20 or 30 MB, so download will take time. I guess mapping and store it in core data will also take time time.
Can I do it in restkit? or has been designed just for reasonable size responses?
I see I can track progress when downloading a large file, even I see I can know when mapping starts or finishes: http://restkit.org/api/latest/Protocols/RKMapperOperationDelegate.html
Probably I can also encapsulate the core data operation to avoid blocking the UI.
What do you think? Do you think is this feasible? Or should I select a more manual approach? I would like to know your opinion. Thanks in advance.
Your problem is not encapsulation or threading, it's memory usage.
For a start, thousands or millions of 'hot posts' are likely to cause you issues on a mobile device. You should usually be using a web service that allows you to obtain a filtered set of content. If you don't have that already, consider creating it (possibly by uploading the data to a service like Parse.com).
RestKit isn't designed to use a streaming parser, so the full JSON will need to be deserialised into memory before it can be processed. You can try it, but I suspect the mobile device will be unhappy if the JSON is 20 / 30 MB.
So, create a nice web service or use a streaming parser and process the results yourself (which, could technically be done using RestKit mapping operations).
In my iOS5-App I do a lot of Request, parsing the results and storing them in CoreData simultaneously.
For doing the requests I use asynchronous ASIHttpRequest.
But the app has perfromance problems while this requests are running. What is a good approach to to this in the background? And how do I avoid conflicts with the context when storing the results to the db? All "commits" are performed in the main-thread because I had problems when putting the requests in a backgroundque.
Can you give me an example or a good pattern to use in my app?
Since ASI is no longer being supported a lot of people switched to AFNetworking.
There's also the minimalistic approach of using NSURLConnections with Blocks.