When to delete files from NSCachesDirectory - ios

I am developing a news application . I am using NSCacheDirectory to save to image's . I want to know when should I delete the images from the cash . I know I could probably delete it when I receive a memory warning (or it would be automatically deleted in a low memory condition) but I don't understand why to keep the images for so long and delete them only if I receive the memory warning . I also tried to check if all the images saved in NSCashDirectory are in the data which I get (from the internet) and if not then delete it , but I am sure performance would be a issue . Is there a way to clear cash after a specific time interval
P.S. I am quite new to iOS programming .

Since you are developing a news application I am going to assume that the news will be updated at certain intervals. This means that you could probably define a lifetime for an article stored on the device. So what you could do is say every day, mark all articles older than seven days as trashable. Then, when it's safe to do so (App launch or when user is reading new content) you can delete said content.
I don't know your audience but traditionally it's safe to assume that people won't read the same article multiple times so you can definitely make your window for stale content quite small.
That being said if you implement a bookmarking facility you could approach this in a similar fashion too. You could for instance assume that the user will most likely interact with the most recently bookmarked articles. Remember, in this recency is defined by the user not the article date. Articles bookmarked most recently by the user will possibly be read or shared more likely than older ones.
You could also have an option in your setting where the user can choose to delete all cached content. Since your content should be living on a server it shouldn't be impossible for the user to fetch old content.
As far as you are concerned each article could be broken up into an article mapping and an article. An article mapping should contain the bare minimum of information to allow for the display of content in an article feed (things like headline, thumbnail URL etc). Where your article would contain all the content. When the user requests to delete all cached data you could delete all the images and keep all the mappings (at least the most recent ones) on the device still.
Happy coding

Related

Removing documents from CouchDB replicas

We have a product that uses central CouchDB databases per client replicating to Apps running on user's iPads. Most of the database can replicate normally but we have two categories of document that we want to filter:
Documents with an owner - we want to filter the replication to only the current users documents (and documents with no specified owner).
Last X documents of some type. For some sorts of documents we only want to leave the last 10 (say) copies on the iPad.
We can set up both rules easily enough using filtered replication - so that the server only presents the subset of documents we want to the iPad for replication. Except... it does not work.
If a document has no owner (replicated) and later an owner is specified, it vanishes from the replication stream - but not from the iPad. In fact the version of the document that remains on the iPad still has NO owner and so we cant even hide it in code.
When a document becomes the 11th oldest and vanishes from the replication stream, it does not vanish from the iPad. Indeed unless the iPad database is rebuilt all versions of these documents end up there, and no longer replicate which is worse than just replicating them all in the first place.
We did find a hacky workaround - in the case where a document gains a new owner OR becomes older than X, we duplicate it and delete the original. The delete propogates to the iPad and the new document is filtered out of replication. This worked well enough (although it is a bit inefficient). However then we realised the newly copied document had lost all of its revision information and we were relying on the revisions to track changes!
So - does anyone have any other suggestion? What we are looking for is a mechanism to pull a document from the iPad replicas on demand. I am aware we could instruct the iPad to delete the documents locally - but then sooner or later those deletes would leak back to the server and destroy the original?
... we were relying on the revisions to track changes
IMHO this is the most interesting point to talk about an alternative solution.
I'm sorry but i have to say you using the CouchDB revision control in the way it that is not recommended. The document revisions are temporary. The best way to track changes of a document is to write a changes log inside or outside the doc.
How would you persist changes outside the doc itself - yes, you would create new docs. Surprise: you "Hack" is the right solution \o/
Maybe you shaking your head and your are not happy because you have tried to remove docs from the iPad to make them invisible client-side. That was the starting point of your "Hack", right?
My recommendation is to not combine "visibility" and "existence". Better would be to use your know-how with building view-indexes server-side in the same way client-side with PouchDB. Let the replication just handle replication - thats hard enough. Use views/filters client- and server-side to solve visibility requirements.

Ship iOS app with pre-populated Parse datastore

Given the recent addition of local datastore for iOS to Parse, it should be possible to rely exclusively on Parse to manage app's database, thus totally avoiding Core Data. Does this sound like a good idea? What would be the pros and cons of such an approach?
In particular, I am wondering whether it will be possible to pre-populate Parse local datastore with some data, and include this database as a part of the app when submitting to appstore.
UPDATE
From the comments that were posted, it seems that people misunderstood my intended use case. Sorry guys, I should have made my question more clear from the beginning. Let me clarify it now, anyway.
So, there is some amount of data in Parse database on the web, same for every user, e.g. a catalogue of books. It will be updated every now and then. What I want is to publish an app on App Store which is pre-populated with Parse data store, as it stands at the moment when the app is published. For that to happen, I'd like to pin all available data when building my app and ship that data store along with the app. The problem is that the pinned data will be stored on device's (or emulator's) file system, it won't be part of the project. That's why if I build the app and submit it to app store, the data won'd be included.
Any suggestions how to attach the local data store to the app?
The local data store is stored in the sandboxed part of the filesystem in iOS. When you package the store with the app, it'll live in the signed application folder, not in the location Parse expects it to be.
So, if you were looking to do this, you'd need to include your default local data store in the application on building/submission, and copy it into the location Parse expects it to be in (which is Library/Private Documents/Parse and the file is called ParseOfflineStore) when your application starts up. This must happen before you call enableLocalDatastore, or an empty one will be initialized.
It should be possible!
Read this in the docs. Parse has a highly resourceful and fully documented guide for their backend.
https://parse.com/docs/ios_guide#localdatastore
Per my comment above concerning didFinishLaunchingWithOptions; it has been a place for your to create objects on launch, I have been doing that for a long time. Especially with channels. However, by enabling the local data store you can access those objects you pinned or created with a simple query with no reachability per your concern. Either way they both are created on disk. Core Data has a lot more cons. Especially with NSFetchedResultsController and the flexibility it offers. It's all up to you what you want to do with your app. PFQueryTableViewController isn't bad but if your direction and vision for your app is to be exclusively Parse then why not. It's a great feature. However I didn't see anything in the docs about the local queries effecting your limit so I would suggest looking into that if you have a large audience performing numerous queries per second.
Take advantage of their docs. They do a great job at keeping us informed.

How is data typically reloaded/displayed on a device when only a tiny amount of data changes after updating the database? (Conceptually)

Here's and example of what I am talking about:
Take Twitter for iOS. Whenever you tweet, the tweet is sent to the database, and then it is also displayed on your device as part of the list of tweets.
How is the list of tweets that you see on your device updated after just sending one tweet? Here are some possible ways that I thought of how it could be done, but what Im asking for is which one is the best method of doing so:
The whole list of recent Tweets is re-downloaded from the remote Twitter server after sending a tweet (I highly doubt this, as this would take a relatively long time, when it really is just appending one Tweet to the array of Tweets displayed)
The local array that holds the Tweet objects is updated separately from the database (For example, it updates the database, and then updates its array with the same data you sent to the database, and never downloads the Tweet you just sent since you don't need to, because you already have it locally, since you composed it)
Is Core Data capable of updating the remote data server AND the array all in one (or relatively few) step(s)? (Sorry, if this is the obvious answer and if it sounds like I didn't look into it, but I did read about Core Data and started a tutorial. Its just that there is so much content that it would take me a whole day or two just to figure out if its appropriate for my application)
Is there an alternative way of managing this?
Also, if its one of the latter two ideas above, are you able to update the table view cells by just updating the local array and reloading the cells from that array without loading your one tweet from the database? I'm just curious about what would be the most efficient way of doing this.
So again, my main question reworded is: how do you keep data that you sent to a remote database and the local data (stored in a mutable array) in sync whenever you do a tiny single update (such as sending a Tweet) without having to reload all of the data from the database (when there is other content [i.e. other Tweets]) already loaded.
(I am aware that no one except Twitter developers know exactly how Twitter actually done, but I'm just using this Twitter functionality as an example. This same concept could be applied to any similar app.)
(Also, this is a conceptual question about dataflow, so I don't need to see any code, but suggestions to use different technologies like Core Data, or just updating an array will be appreciated.)
(I've been looking into this, and all the different ways of doing it, and it is becoming very time consuming, so I figured to ask you guys who have experience. Additionally, this could help someone else who has similar questions.)
(Sorry if it looks like I'm asking a bunch of questions, but I'm basically asking the same question in different ways, and offering possible solutions.)
Any insight is appreciated!
Immutable messages like tweets are actually quite easy to handle -- server side, and in your app.
When you send a tweet from your client to the server, you also update your "main context" (see "Managed Object Context") which in turn sends notifications to your controller (see NSFetchedResultsController which in turns updates your table view according your local model residing in the Managed Object Context.
Updating from the server is just merging the local tweets with the new ones added in the meantime.
Since there is no mutable tweet, synchronization is really no big deal. As mentioned in the comment, if there were mutable tweets (or any kind of messages) the synchronization will become much more complex.
Core Data will NOT automatically update a remote server. But there are solutions to "view" a remote database through Core Data - see NSIncrementalStore and a related third party libraries (AFIncrementalStore).
This is ridiculously trivial. You update your local database and send off the remote update at the same time.
You use the remote response to mark your local record as synched or try updating again later.

iOS App Offline and synchronization

I am trying to build an offline synchronization capability into my iOS App and would like to get some feedback/advice from the community on the strategy and best practice to be followed to do the same. The app details are as follows:
The app shows a digital catalog to users and allows them to perform actions like creating and placing orders, among others.
Currently the app only works when online, and we have APIs for all actions like viewing the catalog, creating/placing orders which return JSON data.
We would like to provide offline/synchronization capability to users, through which users can view the catalog and create/place orders while offline, and when they come online the order details will be synchronized and updated to our server.
We would also like to pull the latest data from the server, and have the app keep itself up to date in case of catalog changes or order changes that happened at the Server while the app was offline.
Can you guys help me to come with the best design and approach for handling this kind of functionality?
I have done something similar just in the beginning of this year. After I read about NSOperationQueue and NSOperation I did a straight forward approach:
Whenever an object is changed/added/... in my local database, I add a new "sync"-operation to the queue and I do not care about, if the app is online or offline (I added a reachability observer which either suspended the queue or takes it back working; of course, I do re-queueing if an error occurs (lost network during sync)). The operation itself reads/writes the database and does the networking stuff. My ViewController use a NSFetchedResultsController (with delegate=self) to get callbacks on changes. In some cases I needed some extra local data (it is about counting objects), where I have used NSManagedObjectContextObjectsDidChangeNotification.
Furthermore, I have used Multi-Context CoreData which sounded quite reasonable to use (I have only two contexts).
To get notified about changes from your server, I believe that iOS 7 has something new for you.
On the server side, you should read a little for the actual approach you want to go for: i.e. Data Synchronization by Dan Grover or Developing Android REST Client Applications (of course there are many more good articles out there).
Caution: you might be disappointed when you expect an easy solution. Your requirement is not unusual, but the solution might become more complex than you expect - depending on the "business rules" and other reasonable requirements. If you intelligently restrict your requirements you may find a solution which you can implement yourself, otherwise you may also consider to use a commercial product.
I could imagine, that if you design the business logic such that it takes an offline state into account and exposes this explicitly in the business logic, you may find a solution which you can implement yourself with moderate effort. What I mean by this is for example, when a user creates an order, it is initially in "not committed" stated. The order will only be committed when there is access to the server and if the server gives the "OK" that this order can actually be placed by this user. The server may also deny the order, sending corresponding messages to the user.
There are probably quite a few subtle issues that may arise due to the requirement of eventual consistency.
See also this question which contains pointers to solutions from commercial products, and if you visit their web sites give valuable information about the complexity of the problem and how this can be solved.

iOS data base architectural decision

Newbie question.
I will need to have a data base from about 200 UIImages (single of them less than 500kb size) for iPad app. Customer want to have possibility to change set of this images from time to time without releasing new version of app in appstore and app must work without connection to the web (local data base on a device). I don't see how this can be done simultaneously, I see only one common option here:
Image data base would be stored on a server, what app customer will be able to change anytime. User will need to have web connection and every time he will start the application - existing data base will load into the app.
Main questions here:
is it possible to update data base on user's device without releasing new version of app and what data base managing system is more proper to this situation(SQLite, MySQL etc...)?
Q : is it possible to update data base on user's device without releasing new version of app?
A : Yes. It is possible.
SQLite will be perfect for you.
The photographs reside on the web server.
A number of start-off photographs may reside within the boundle so that the app is not really empty at start.
However, when downloading the app, the user must be online. In most cases he would still be online directly afterwards when he launches the app for the first time.
The server provides two services:
A quick one that just provides a version number of the
photo-database content and/or the date of the last change to the
photographs on the server.
The app frequently (not more than daily I would say) checks wether there are new images on the server or not.
If they are then the user is asked, whether he wants to download them.
If the user says YES then the app sends the version number and/or last date and/or IDs of all local photographs to the server and the
server provides the information about which photographs have been
added and where to download that very photograph and which have to
be deleted.
Then you add or delete or update the photographs from the download source given by the server. (That may well be an URL to the
very same server of course.)
For 200 data sets I would strongly suggest core data with SQLite - the standard stuff.
You may then think of holding the image data in the file system or in NSData properties within the database.

Resources