How to use sharing with CoreData/CloudKit synching - swift

I have an app that works well synchronizing the local core data records with a private database. I would like to make the CloudKit database a shared database and then selectively share records with users. Is this even possible.
In other words, I'd like to continue having the Core Data/CloudKit sync working, but with the records that get synched limited to the user's share(s).
Does anyone have examples or a link to a discussion of this?

Apple solved this last year at WWDC21
Here is a link to the video
https://developers.apple.com/videos/play/wwdc2021/10015/
and some useful example code:
https://github.com/delawaremathguy/CoreDataCloudKitShare

Related

Find out since how long the cache has been stored in IndexDB?

I am using a web application for doing data entry which has a mechanism for storing the data entry form (which is an html form) in the browser cache IndexDB.
I am able to see the form in the browser dev tool like so :
I want to know for how long the Index DB will be able to store the form in the browser? Is it possible that it is months since the browser cache was same? Will closing the browser clear the keys? or is this persistent enough storage to last for a few months?
Is it possible to find out when(the exact date or time) the cache entry was made in the IndexDB?
I am asking this because I suspect some discperancy in the form for some of our users as the data being sent is a little different than expected.
Any help would is appreciated.
Thanks
DHIS2, the application you are referring to, has an application you and other users can use to clear any cached data. This app is named "Browser Cache Cleaner", and gives you a list of different things to clear. I would try this app and see if your users still have these issues.
Databases don't expose the timestamp of when the database record was last modified. That's something the developer needs make the application to store in the database records. For example, one could have created_at and modified_at columns to track when the record was created and when was it last modified.
IndexedDB is a persistent client storage API, so yes, data will stay permanently unless the user clears the browser's cache.
If there is some discrepancy in the form being sent, I would look at the caching strategy. Offline data caching is a pretty broad topic (also I don't know much about your application), but Google's Offline Cookbook is a good place to start digging in this topic, as long as caching strategies for your use.

How to get the actual quota for CloudKit?

Im using Cloudkit and the private database to store some files to iCloud and sync between iOS und OSX.
Now I wanted to implement something, the user can see how much space is left in his iCloud without leaving the app and look in the preferences. But I cant't find any information how to get this data. The whole CloutKit Framework reference has no object or method that gives me this information.
Because the private database uses the normal iCloud quota of the user, I could work around by looking for this data over any other iCloud API.
Anybody has an hint for me or a way to get this infos?
There isn't currently a way to get the remaining quota for a user in the private database at this time, so your best option is to just try to upload the data you want and watch for a CKErrorQuotaExceeded error.

Is there any value in using core data for iPhone apps?

Can people give me examples of why they would use coreData in an application?
I ask this because most apps are just clients to a central server where an API of some sort gives you the information you need.
In my case I'm writing a timesheet application for a web app which has an API and I'm debating if there is any value in replicating the data structure on my server in core data(Sqlite)
e.g
Project has many timesheets
employee has many timesheets
It seems to me that I can just connect to the API on every call for lists of projects or existing timesheets for example.
I realize for some kind of offline mode you could store locally in core data but this creates way more problems because you now have a big problem with syncing that data back to the web server when you get connection again.. e.g. the project selected for a timesheet no longer exists.
Can any experienced developer shed some light on there experiences on when core data is best practice approach?
EDIT
I realise of course there is value in storing local persistance but the key value of user defaults seems to cover most applications I can think of.
You shouldn't think of CoreData simply as an SQLite database. It's not JUST an SQLite database. Sure, SQLite is an option, but there are other options as well, such as in-memory and, as of iOS5, a whole slew of custom data stores. The biggest benefit with CoreData is persistence, obviously. But even if you are using an in-memory data store, you get the benefits of a very well structured object graph, and all of the heavy lifting with regards to pulling information out of or putting information into the data store is handled by CoreData for you, without you necessarily needing to concern yourself with what is backing that data store. Sure, today you don't care too much about persistence, so you could use an in-memory data store. What happens if tomorrow, or in a month, or a year, you decide to add a feature that would really benefit from persistence? With CoreData, you simply change or add a persistent data store, and all of your methods to get information out or in remain unchanged. The overhead for that sort of addition is minimal in comparison to if you were trying to access SQLite or some other data store directly. IMHO, that's the biggest benefit: abstraction. And, in essence, abstraction is one of the most powerful things behind OOP. Granted, building the Data Model just for in-memory storage could be overkill for your app, depending on how involved the app is. But, just as a side note, you may want to consider what is faster: Requesting information from your web service every time you want to perform some action, or requesting the information once, storing it in memory, and acting on that stored value for the remainder of the session. An in-memory data store wouldn't persistent beyond that particular session.
Additionally, with CoreData you get a lot of other great features like saving, fetching, and undo-redo.
There are basically two kinds of apps. Those that provide you with local functionality (games, professional applications, navigation systems...) and those that grant access to a remote service.
Your app seems to be in the second category. If you access remote services, your users will want to access new or real-time data (you don't want to read 2 week old Facebook posts) but in some cases, local caching makes sense (e.g. reading your mails when you're on the train with unstable network).
I assume that the value of accessing cached entries when not connected to a network is pretty low for your customers (internal or external) compared to the importance of accessing real-time-data. So local storage might be not necessary at all.
If you don't have hundreds of entries in your timetable, "normal" serialization (NSCoding-protocol) might be enough. If you only access some "dashboard-data", you will be able to get along with simple request/response-caching (NSURLCache can do a lot of things...).
Core Data does make more sense if you have complex data structures which should be synchronized with a server. This adds a lot of synchronization logic to your project as well as complexity from Core Data integration (concurrency, thread-safety, in-app-conflicts...).
If you want to create a "client"-app with a server driven user experience, local storage is not necessary at all so my suggestion is: Keep it as simple as possible unless there is a real need for offline storage.
It's ideal for if you want to store data locally on the phone.
Seriously though, if you can't see a need for it for your timesheet app, then don't worry about it and don't use it.
Solving the sync problems that you would have with an "offline" mode would be detailed in your design of your app. For example - don't allow projects to be deleted. Why would you? Wouldn't you want to go back in time and look at previous data for particular projects? Instead just have a marker on the project to show it as inactive and a date/time that it was made inactive. If the data that is being synced from the device is for that project and is before the date/time that it was marked as inactive, then it's fine to sync. Otherwise display a message and the user will have to sort it.
It depends purely on your application's design whether you need to store some data locally or not, if it is a real problem or a thin GUI client around your web service. Apart from "offline" mode the other reason to cache server data on client side might be to take traffic load from your server. Just think what does it mean for your server to send every time the whole timesheet data to the client, or just the changes. Yes, it means more implementation on both side, but in some cases it has serious advantages.
EDIT: example added
You have 1000 records per user in your timesheet application and one record is cca 1 kbyte. In this case every time a user starts your application, it has to fetch ~1Mbyte data from your server. If you cache the data locally, the server can tell you that let's say two records were updated since your last update, so you'll have to download only 2 kbyte. Now you should scale up this for several tens of thousands of user and you will immediately notice the difference of the server bandwidth and CPU usage.

Retro-fitting my app for iCloud

I have been puzzling about retrofitting my app for iCloud for a few days and hope someone can help. After getting past code signing issues I am not sure I understand the model for incorporating iCloud. I'll tell you the problem I'm trying to solve first since I'm a big believer in telling people what I'm trying to do before having them try to fix the way I'm doing it :-)
My app workflow
User browses the store which lists a series of training plans they can download
User picks a plan and downloads it
I pull the training plan from our webserver customized to their needs
I add the filename for the training plan they downloaded to a plist of plans they own
User opens the training plan and sees the day-to-day schedule
I want the user to be able to do this on their iPhone and then open their iPad and see the exact same training plans synced over there.
My problem
I currently save the files to the Documents directory and that works just fine. How do I retrofit this to work with iCloud such that folks without iCloud enabled can continue to use the app but those who do get the added benefit?
My understanding
I'm confused as to whether I still need to save to Documents folder and then save a copy to the iCloud folder OR whether I just write to the iCloud folder from now on.
If it's the former I believe I just write a copy the Documents folder files to the iCloud area too to push it up but how do I detect a new file in the iCloud folder and copy it back to my Documents folder?
If it's the latter the files should just exist right?
I'm hoping it's the latter and that still supports devices without iCloud turned on...
Thanks for any help clarifying.
Adam
The iCloud API is pretty well documented and there is a specific chapter that deals with what you are after:
Managing the Life Cycle of a Document
A document goes through a typical life cycle. A document-based
application is responsible for managing its progress through that
cycle. As you can see from the following list, most of these
life-cycle events are initiated by the user:
The user first creates a document.
The user opens an existing document and the application displays it in the document’s view or views.
The user edits the document. A user may ask to put a document in iCloud storage or may request the removal of a document from iCloud storage.
During editing, saving, or other actions, errors or conflicts can happen; the application should learn about these errors and conflicts and either attempt to handle them or inform the user.
The user closes a selected document. The user deletes an existing document. The following sections discuss the procedures a document-based application must complete for these life-cycle operations.
In essence, you application is responsible for working out whether iCloud is available for a particular user and then confirm that the user wants to store their data in the cloud. Based on that selection you will need to work out how to move their existing data from the documents directory to a cloud URL.
On other devices that are setup to use iCloud storage, you have the option to discover documents available via a metadata query.
http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/DocumentBasedAppPGiOS/ManageDocumentLifeCycle/ManageDocumentLifeCycle.html#//apple_ref/doc/uid/TP40011149-CH4-SW1
If you are looking for a very easy sample which implements iCloud, have a look at this:
iCloud basics and code sample
This gives you a concrete example of how to implement some of the stages Rog has cited in his post above. Hope this helps.

Overwrite database or update (iPhone)?

I have a content based, read-only iPhone app. Users can select favorite topics, which I need to track. Some topics I'd like to make available between app updates through the App Store. I'll need to track if users have downloaded these particular topics or not until the App Store update is available. This approach will consist of two tables for user tracking. All other tables contain mainly static content, save any new downloaded entries.
Before I began tracking user content, I'd always deploy the database on app updates. An overwrite - simple. But now I need to track certain user configurations. Rather than trying to keep track of which app version a user has and running through a list of sql scripts in the correct order, so the user is at the right database version, I'm thiking to use two databases. One contains static content and the other user data. The static content database is always overwritten. That keeps things simple. The database currently is 250kb. It will grow very slowly.
I have plans to use SDK 3.0 push notification and peer-to-peer as well, which will store any user config data in the user database.
Any one see problems with this approach?
This sounds alright to me. If you're using SQLite, you may want to look into the ATTACH DATABASE command, which lets you keep two databases open on the same connection.