Strategies on synching data and caching data between iphone and server - iphone

Say I have a TODO list iphone app, that can be edited/viewed from both a web application and the iphone application.
When on the iphone, when a user views all his todo lists, or sub-items, I would think that each time the user views a particular list it shouldn't be hitting the web applications API every-time, but rather cache locally the values and only hit the web when things change.
What strategies are there for this type of scenerio?

I agree with you in your dirty-otherwise-do-not-contact-the-server point. And I think this point is pretty straightforward and easy to implement.
However, be careful in this scenario: it gets dirty but at the same time, the device cannot reach the internet. In this scenario, I suggest you check the internet accessibility on a frequent basis (even when your app is in the background), and try to reach your server and update whenever possible.

This is a tricky problem. I'm currently working on an app that needs to perform a similar synchronization, and I haven't decided how I want to handle it yet.
You're right in that you don't want to be hitting the web repeatedly. It would slow the app down considerably. Keeping a local cache is the way to go.
One drawback is that the user could change/add an item on the web and you wouldn't see it on the phone. You'd need to have a refresh button (like in the Mail application, for example) to allow the user to get the changes.
Then you have an issue with conflict resolution. Say the same item is edited on both the phone and on the web. How does the user pick which one to keep, or do they get duplicated?

I think the best way to do this is to replicated your server's schema in CoreData. Then load a given element from the local DB, and in the background go out and check that element for updates if the device has an internet connection. You're hitting the db each time, but the user is not slowed down by the process.

You should not query the internet everytime you view the list.
But when you make updates to it, or edit it, you should update the server as well. That will make your life a whole lot simpler. That way when the user updates an item that he deleted in the web server, the server will just throw that request out...

Related

IndexedDB persistence in PWA application

PWA application storage (IndexedDB) isn't able to provide data persistence.
In case that PWA is pinned to home screen it is possible to clear all application data from browser by clearing browsing history.
It might be unclear for users that cleaning browser data can affect pinned application and unsynchronised data will be lost.
Is there any way to avoid this?
The only way I see for now - turn back to native apps.
The clear storage mechanism in browsers is to put the user in control of their device.
This is why you as an application should never (native or web) assume your cached assets are cached.
If it is absolutely important to you to make sure you have core assets and data persisted then you need to have some sort of integrity check when the service worker initiates. That way you can restore cached state in case the application goes offline.
You also need to realize the operating system, looking at you iOS, will purge data when it feels like it (think when the available disk space gets critical), which takes you out fo control. It does this for native apps too as far as I know.
I do not know a way around that. The function in Chrome to "clear storage" (for example) does exactly that. I suppose it is reasonable for a user to be able to remove any data from their own device, but I agree it is not a good situation for the developer.
This is not possible.
The Storage API provides a StorageManager.persist() method to request the user explicit permission to persist data until deleted by the user itself:
if (navigator.storage && navigator.storage.persist)
navigator.storage.persist().then(function(persistent) {
if (persistent)
console.log("Storage will not be cleared except by explicit user action");
else
console.log("Storage may be cleared by the UA under storage pressure.");
});
If the local storage is running out of space, the User Agent will start automatically pruning cached resourced except the ones set as "persistent". However if the user itself chooses to clear the local data, there is no way to prevent this.
As far as I am aware, there is no event you can intercept in order to detect a browser clear action from the user.
See API reference doc :
https://developer.mozilla.org/en-US/docs/Web/API/StorageManager/persist

How can I run server-side realtime database queries

I am using Firebase's Realtime Database.
I am able to use my old device and permanently keep it on for checking if the host has left a party to therefore notify the users. However, this is inconvenient and there must be a simple server side solution.
I know how to code it (using .observe etc.) but I don't know where to run the code. The code will be on a loop to check if a host has left every 10 seconds (this is because the host may run out of battery so the database is not notified). Can I simply run it in functions somehow? Or using hosting?
The server code will send a request to the host, and if there is no response, the party has therefore been closed so it will tell the users.
Any help or pointers in the right direction are greatly appreciated.
If you have any questions, please ask!
It's not related to the iOS. Put your initial code into the viewDidLoad or init methods (depends on how do you write the code) and forget about it. Those methods are called once per an instance. For now Firebase works fine on your usecase. At least I don't have any wierd updates on the observe method. also you can specify what do you want to observe exactly in the Firebase (something like the new or last 15)
The solution to this was that even if the user left the app, they would still be in the party. I used user defaults so it can remember if the user was in a party so it can return them.
I also used Realtime Database triggers which can remove all information about a user with one action in the app (so all data gets removed, and not left behind, which would create a waste of unusable database memory).

Recreating core data at application launch

I have an app that connects to a website. I store its data as core data and then I use the core data to load my tableviews. I believe, I want to reload the data from the website every time I launch the app, since the user could change the data if they were to go onto the website.
What's the best way to approach this? Should I just delete the core data each time the app terminates?
It depends on how critical it is that data on the device always be current, on how long you expect users to wait before working with the app, and on what you want to happen if someone tries to use the app when the network is slow or unavailable. If you delete the store, and the app can't connect immediately, the user has no data. Even if the network is fine, the user still has to wait on network and server latency before they can start using the app. This is likely to be poor UX.
On the other hand if you allow data to persist after the app exits, the user's data might not be current, at least not at first.
If you don't ever want the data to persist after the app exits, an in-memory store might be the best choice, because it will never be saved to a file anyway.
If presenting potentially old data is OK either (a) briefly when the app starts up or (b) when the network is unavailable, a better choice would be to keep the data store but make new network calls to update the existing data. You could provide some sort of UI to indicate that updates are in progress. You might also have some in-app indication of when your app last synced with the server.
I'm not sure of how your application makes use of the Core Data stack, but if you don't care about (or don't have) changes made locally on the device, I'd say the easiest way to refresh the data from the server is just what you said: wipe out the store file, re-create it and import the data from the server. However, I wouldn't do this systematically on each application launch. Make sure the user knows about it and think of providing a "refresh" button to trigger that procedure. Also make sure you can download new content from the server, before wiping out the local store.
If you want to load all the data in memory (and also want to do updates) then you can create a managed object context backed by a NSAtomicStore persistent store subclass. In the NSAtomicStore subclass you can implement the read: (load: method) and the CRUD actions (newReferenceObjectForManagedObject:, save: and updateCacheNode:fromManagedObject: methods)

Core Data with Web Services recommended pattern?

I am writing an app for iOS that uses data provided by a web service. I am using core data for local storage and persistence of the data, so that some core set of the data is available to the user if the web is not reachable.
In building this app, I've been reading lots of posts about core data. While there seems to be lots out there on the mechanics of doing this, I've seen less on the general principles/patterns for this.
I am wondering if there are some good references out there for a recommended interaction model.
For example, the user will be able to create new objects on the app. Lets say the user creates a new employee object, the user will typically create it, update it and then save it. I've seen recommendations that updates each of these steps to the server --> when the user creates it, when the user makes changes to the fields. And if the user cancels at the end, a delete is sent to the server. Another different recommendation for the same operation is to keep everything locally, and only send the complete update to the server when the user saves.
This example aside, I am curious if there are some general recommendations/patterns on how to handle CRUD operations and ensure they are sync'd between the webserver and coredata.
Thanks much.
I think the best approach in the case you mention is to store data only locally until the point the user commits the adding of the new record. Sending every field edit to the server is somewhat excessive.
A general idiom of iPhone apps is that there isn't such a thing as "Save". The user generally will expect things to be committed at some sensible point, but it isn't presented to the user as saving per se.
So, for example, imagine you have a UI that lets the user edit some sort of record that will be saved to local core data and also be sent to the server. At the point the user exits the UI for creating a new record, they will perhaps hit a button called "Done" (N.B. not usually called "Save"). At the point they hit "Done", you'll want to kick off a core data write and also start a push to the remote server. The server pus h won't necessarily hog the UI or make them wait till it completes -- it's nicer to allow them to continue using the app -- but it is happening. If the update push to server failed, you might want to signal it to the user or do something appropriate.
A good question to ask yourself when planning the granularity of writes to core data and/or a remote server is: what would happen if the app crashed out, or the phone ran out of power, at any particular spots in the app? How much loss of data could possibly occur? Good apps lower the risk of data loss and can re-launch in a very similar state to what they were previously in after being exited for whatever reason.
Be prepared to tear your hair out quite a bit. I've been working on this, and the problem is that the Core Data samples are quite simple. The minute you move to a complex model and you try to use the NSFetchedResultsController and its delegate, you bump into all sorts of problems with using multiple contexts.
I use one to populate data from your webservice in a background "block", and a second for the tableview to use - you'll most likely end up using a tableview for a master list and a detail view.
Brush up on using blocks in Cocoa if you want to keep your app responsive whilst receiving or sending data to/from a server.
You might want to read about 'transactions' - which is basically the grouping of multiple actions/changes as a single atomic action/change. This helps avoid partial saves that might result in inconsistent data on server.
Ultimately, this is a very big topic - especially if server data is shared across multiple clients. At the simplest, you would want to decide on basic policies. Does last save win? Is there some notion of remotely held locks on objects in server data store? How is conflict resolved, when two clients are, say, editing the same property of the same object?
With respect to how things are done on the iPhone, I would agree with occulus that "Done" provides a natural point for persisting changes to server (in a separate thread).

get data from online once and then viewable offline

Okay, I want to have an app that takes phone numbers from an online database and displays them in a table view. When the user is not online, I want them to still be able to see the numbers they already got from the database in the table view. If the user manages to go back online, the database updates the view. My question is, is this possible to do and if so, what's the best way to approach it? (bit of a newbie, please help me out)
There are many ways to do what you are asking, depending on the complexity of what you are after.
Could I suggest the following steps (I'm not sure which ones you can do, and which ones you are having trouble with).
Connect to the server and retrieve the list of phone numbers
If the database has a web server front end this might be as simple as sending a get request to the server (see NSURLConnection) and parsing the result. Otherwise you will need to know/tell us what type database you are using.
Store the phone numbers on the device
Use SQLite to store the numbers on the device (See iPhone SQLite Resources)
Check for internet connectivity
Periodically check for internet connectivity, and if a specific time has elapsed since you last polled the server, retry. (See Checking iPhone internet connectivity)
Although you’re probably looking for a native app solution, you can also do this with a web app.
http://diveintohtml5.ep.io/offline.html
I am a new developer iPhone developer, "learning" to be precise. I came across the useful NSUserDefaults (a dictionary in which you can store/restore state even after your application relaunches). Problem with this dictionary will be memory in your case. NSUserDefaults is sort of global to all applications and yours may spoil the show for other innocent applications (like Weather :D ).
To work around this, you can have your application declare a property list file where you store a few numbers (best practise would be the most recent but you can use any selector of choice). Look for an appropriate time in your run loop to store these numbers into your property file and load them when the application starts.