UIDocument or UIManagedDocument when the application's backing store is both file & core data database - core-data

I am bit confused regarding which class I should inherit from. My application currently creates files in the "Documents" folder and also has Core Data based data models. These data models contains more information about the files.
Now I am thinking to migrate the app to the document architecture and thereby integrating with iCloud at one of time.
I have started to think in the direction of using both i.e. using UIDocument to manage the files and UIManagedDocument to manage the Core Data.
Would appreciate if someone could guide me.

It is perfectly acceptable to use both at the same time, as you said, for different purposes.
But consider, if those files are real documents and not just some data files of an internal implementation, I personally would not store any critical data about the documents separate from the documents though. Since documents from user perspective are meant to be self-sustaining - user may create, delete or move them around freely without fearing any interdependency with some other documents or objects. User expects all necessary meta-data to move with the document.
Then again if there is some "house-keeping" metadata that you can always re-create about your documents in the database, that is just fine.

Related

How to sync records between Core Data and CloudKit efficiently

I'm currently learning how to use CloudKit Framework and lack of documentation or examples showing how to sync Core Data and CloudKit.
I have watched all WWDC videos (2014, 2015, 2016) Dedicated to CloudKit, but none of them telling us how to implement syncing with Core Data. I can't find any fresh examples, tutorial or books, showing how to implement this syncing.
I know that it is effective to use Operations API by CloudKit (not Convenience API) and to Subscribe to changes as it said in the new WWDC 2016 videos, dedicated to CloudKit, but mapping with CoreData is a real problem.
For example, let's say I would like to create an app similar to Notes app. while offline, user can create his notes and work with them saving them to his core data database. When the device going online the app checks what changed on the server and saves newly created records to server (CloudKit).
When the app starts, it also fetches for changes from the CloudKit and if there are changes , it updates local cache (Core Data) with the new changes.
I would appreciate to have a common pattern of syncing. Where to place syncing with Core Data methods and how they should look like?
Would appreciate any information or help about this.
I'm using Swift 3, Xcode 8 , iOS 10.
As of iOS 13, there are new API's that simplify this synchronization for developers. I would recommend you to watch the WWDC19 session about the new synchronization between CoreData and CloudKit. Please note that these new API's only work for iOS 13+.
Video: https://developer.apple.com/videos/play/wwdc2019/202/
In short, you need to start using NSPersistentCloudKitContainer instead of NSPersistentContainer. This will let the syncing work automatically using automatic conflict resolution with a last-writer-wins merge strategy. If you want to build a good working app, you'll also need to do some modifications to improve the syncing for your app.
Official documentation can be found at:
Setting Up Core Data with CloudKit
Syncing a Core Data Store with CloudKit
Data modeling for collaboration (conflict-free replicated data type)
At the end of the session they also demonstrated an example of better sync merging than the default 'last-writer-wins merge strategy'. The usage of Causal Trees allow multiple users to edit the same string (and to some extend other types of data) without losing any data. I would really recommend everyone to read this article from Archagon that describes how this works and how to implement it (also with CloudKit syncing, but not the new automatic one). As demonstrated in the session, you can also implement this with the new automatic syncing between CoreData and CloudKit.
Core Data already provides the user with the ability to sync to iCloud. There's no need to use CloudKit.
Design For Core Data In iCloud
But yes, Core Data with iCloud has been deprecated. Even so, it has not been discontinued, and there are no immediate plans at apple to discontinue it, they just want to discourage its use. But it also has problems with rationalising updates from multiple devices.
In any case, I have been looking into the question of how to do this with cloud kit myself. Two answers; the first is to use the following;
Seam in GitHub
The second is to do it manually;
Designing for CloudKit
The key here is that Cloud Kit needs the record metadata to be able to handle record updates reliably, so you have to save that metadata in your Core Data database. The CKRecord class includes a method encodeSystemFields(with:) which will encode those fields into a Data record that can be stored in your database, and then your can use the appropriate decoder when you need to restore the CKRecord.
Anyway, I am about to start doing this myself. I'll update this with more information when I have it.
Apple has recently published a guide that seems to answer this question. Check out Apple's Maintaining a Local Cache of CloudKit Records to see how to store CloudKit data on device.
While this guide doesn't provide sample code to write to the device, it does answer the rest of the question. This tells you how to fetch changes from CloudKit and create data which can be stored on the device.

Two Coredata Persistent Stores in one App

The app I'm working on at the moment has a read-only Core Data library full of questions (for kids to answer) that I'd like the freedom to quickly replace via app updates (ideally just by replacing the sqlite backend database in the user's documents folder if it's different to the version in the application bundle).
I'm also storing data created by the user that I don't want to lose when I replace the question database.
Is it feasible (and good practice) to have two persistent stores and data models in the same app, one which I can replace and one that remains, er, persistent through updates?
Yes. You can just have two separate Core Data stacks (two persistent stores, managed object models, and managed object contexts). Doing anything to one should not affect the other. If you want, they can also share the same managed object model, but it may be simpler to keep two separate ones if the two stores are completely independent.

How Does the Single Store Xpages work?

I have a number of XPAges design elements that I use in many different databases. If I read the wiki correctly the single store is an all or nothing situation.
So I want to create unique design in a database but use the set of reusable XPages element from a single store location. the wiki says:
Apart from the "dummy or blank XPage with the same name of the default XPage" in each instance application, does it matter if an 'instance' contains XPage design elements?
No. If SCXD is set on an application all XPages design elements are ignored on the database and the application uses the design elements on the SCXD database.
If this is the case then I have to create databases where probably 75% of the code is reusable but I would have to repeat it (and maintain it) in dozens of separate databases. pity!
XPages and related elements (Custom Controls, SSJS Libraries, Java Code) can be inherited from a specific template like other design elements. So, I would setup a database called, perhaps, "Core Components" (.ntf or .nsf) with a template name of "CoreComponents". Then on the individual elements in the target DB you would set inheritance to be specifically from the "CoreComponents" template. Then the elements that are unique to each database do not inherit from any template. You can then use File-Application-Refresh design to update the elements with specific inheritance and the one which are unique in that database will not get overwritten.
You do need to do a clean build after the refresh, so I recommend that you keep the Core Components database locally or on a different server than the others so that the daily design task will not update them resulting in corrupted xsp elements.
IBM's preferred model for reusing XPage artifacts across multiple applications is to create OSGi plugins that leverage the XPages Extensibility API.
NotesIn9 episode 64 demonstrates how to make an existing Custom Control design element a library component, which can then be used in any app that has the library available, instead of having to copy the design element to each app separately. Any subsequent changes to that component are then applied immediately to any apps that use it when a new version of the library is deployed.
If you truly have "dozens" of apps that all share certain features, but the entire design should not be identical across all of them, then the OSGi model is definitely the way to go.
But why not flip the entire model on its head? Traditionally, we've always put the code and the data in the same place (e.g. same NSF) because it was a pain to access -- and, especially, visually represent -- data in one NSF via code in another NSF. That's not true anymore. Why have dozens of apps just because the data lives in dozens of places? Any data source in XPages can be told where the data lives... you can link a central user interface to any number of "remote" data stores (either different NSFs on the same server, or even databases on other servers).
Red Pill, for instance, takes this to its logical extreme: they deploy one NSF, which acts as a portal to all your data, no matter where that data lives. The ACLs of the various NSFs (and Readers fields) still ensure that users don't pry into data they haven't been granted access to, and they have complex analytics algorithms for determining which data the users will actually care about. But if you have 500 NSFs in the domain, you're not maintaining 500 different code templates... it's literally just 1; but that one user interface is how users find, and interact with, all their data.
You certainly don't have to take this premise to that extreme, but perhaps you could identify, say, 5 apps where the UI and / or business logic is similar (or even identical), but the data just lives in multiple places. Create one central app for interacting with all of that data. Create a "homepage" that gives users a way to select which "app" they're trying to access (or, if they should only have access to one to begin with, compute which one that is), and then once they navigate in to the specific "app", just bind the data sources to the relevant NSF instead of assuming each view or document lives in the same NSF that the code does.
It's still a good idea to be aware of the Extensibility API, not only for the sake of code reusability, but also to understand just how much of the behavior of the platform truly is within our control now -- provided, of course, that we're willing to occasionally write some custom Java code. But if you shift away from the one-to-one mapping between code and data that we've habitually maintained in Domino for so long, I can practically guarantee that you'll prefer this approach... both for the ease of implementation and maintenance, and for the comparative simplicity it offers to end users.
You can combine the template technique and the all-code-in-one-database approach:
Divide the application design into two parts: a data part and a code part.
The data part contains all Notes views. If it's an classic Notes application it would contain also all design elements for Notes client like Forms, Subforms, Frames and so on.
The code part contains all XPages, Custom Controls, CSS, client/server JavaScript libraries, Themes, images, jars and so on.
Put your 75% common code into masterData.ntf and masterCode.ntf.
The application code databases appCodeX.ntf inherit all design elements of masterCode.ntf and contain the additional application specific design elements.
The code from all application templates gets united in allCode.ntf. It inherits all from masterCode.ntf and inherits the additional pieces of code from application templates.
Based on that you create an allCode.nsf.
On the data side you use the classic template way.
From here you have to possibilities:
You use Single Copy XPage Design - connect every appData database with allCode.nsf
You connect your XPages in allCode.nsf with appData databases
I prefer the latter. You can define in allCode.nsf where all the application data databases are located, e.g. in property documents.
With the approach showed in picture you're still able to separate application easily e.g. in case you want to sell them. You have already a separate template for every single application.

Restricting resource access in CouchDB to exactly 2 users

Currently I'm in the process of evaluating CouchDB for a new project.
Key constraint for this project is strong privacy. There need to be resources that are readable by exactly two users.
One usecase may be something similar to Direct Messages (DMs) on Twitter. Another usecase would be User / SuperUser access level.
I currently don't have any ideas about how to solve these kind of problems with CouchDB other than creating one Database that is accessable only by these 2 users. I wonder how I would then build views aggregating data from several databases?
Do you have any hints / suggestions for me?
I've asked this question several times on couchdb mailing lists, and never got an answer.
There are a number of things that couchdb is missing.
One of them is the document level security which would :
allow only certain users to view a doc
filter the documents indexed in a view on a user level permission base
I don't think that there is a solution to the permission considerations with the current couchdb implementation.
One solution would be to use an external indexing tool like lucene, and tag your documents with user rights, then issue a lucene query with user right definition in order to get the docs. It also implies extra load on your server(s) (lucene requires a JVM) and an extra delay for the data to be available (lucene indexing time ... )
As for the several databases solution, there are language framework implementations that simply don't allow to use more then one databases ( for instance couch_potato for Ruby ).
Having several databases also means that you'll have several replication processes if your databases are replicated.
Also, this means that the views will be updated for each of the database. In some cases this is better then have huge views indexed in a single database, but it also means that distinct users might not be up to date for a single source of information ( i.e some will have their views updated, other won't). So you cannot guarantee that the data is consistent for all users.
So unless something is implemented in the couch core in order to manage document level authorizations, CouchDB does not seem appropriate for managing data with privacy constraints.
There are a bunch of details missing about what you are trying to accomplish, what the data looks like, so it's hard to make a specific recommendation. You may be able to create a database per user and copy items into each users database (for the DM use case you described). Each user would only be able to access their own database, and then you could have an admin user that could access all databases. If you need to later update those records copying them to multiple databases might not be a good idea, and then you might consider whether you want to control permissions at a different level from storage.
For views that aggregate data from several databases, I recommend looking at lounge and bigcouch, which take different approaches.
http://tilgovi.github.com/couchdb-lounge/
http://support.cloudant.com/faqs/views/chained-mapreduce-views

Help understanding saving data please. Core data vs plist

Is every app that allows users to input data built with core data?
I've built a "grocery list" type of table view app where you name the list and then in a detail view add items to the list. Simple.
What I don't get is this, based on an iphone development book the example saves the data to a plist using dictionaries.
I've learned that it works on the simulator but not the device because the data is saved to the application bundle not the document directory (which was new to me!)
On the device the app works great except-it won't HOLD the data.
Is core data or sqlite the only solution?
Is every app that allows users to input data built with core data?
Note that your question as posed is incorrect, as it assumes that CoreData is tied to SQLite and is an alternative to plists.
CoreData is a framework for object lifecycle and graph management. It provides implementation of common tasks like changes tracking and propagation, consistency enforcement, data validation and so on.
The CoreData framework is a separate from the object persistence layer and can use different serialization implementations, including SQLite and XML (plists).
For more details, read Core Data Programming - Persistent Store Features.
The decision whether you should use CoreData should be based on whether you need any of the features it provides. If you need to serialize simple object graphs, without consistency requirements, you can use standard NSDictionary to serialize your data in a simple plist file in any of the application-writable folders. Otherwise, use CoreData, and choose the proper persistent store based on the type of data you will be storing.
From what I've seen around the internet, you can use Core Data (which gives you the options of SQLite, atomic, and XML), you can use NSKeyedArchivers and NSKeyedUnarchivers (http://www.vimeo.com/1454094) or you can store the data inside the local application folder (possibly using a serialization method). It looks like Core data is the best solution, but a more complex one to implement. For a simple app, as yours is, I think serializing data and storing it in the local app directory would be perfect.
I am surprised that your book is showing an example where user data is written to the app bundle. Actually, I'm a little surprised that that is even possible.
You should be able to write your data to an NSDictionary (or NSMutableDictionary) and then write that to your app's Documents directory, using -writeToFile:atomically:
Reading data back in should also be straightforward, using -initWithContentsOfFile:.
For someone just getting started, I would recommend keeping it simple. Working NSDictionary is very simple, though you have to manage things like the list of lists and how to name lists that are stored in Documents directory, etc.
Ultimately, using Core Data would probably be a better approach. It offers more flexibility and more power - but, as ever, those advantages come at a cost.
Your question is very important to the community in the respect that
you are asking a strategic question: which technology do I use, when?
Core Data is best for the day-to-day work of a list-based app. Core data is built to mirror the storage of data, similar to how databases work. Relational structures, sorting, key indexing and other row-based attributes are best supported by Core Data.
Property Lists (*.plist) is best suited to one-time updates to critical environmental settings. The user, for example, can optionally set .plist attributes through IOS Settings app. So passwords, account settings, email addresses, and configuration options can be set here nicely. This kind of data is very different from frequently-updated, transactional data.
XML Persistence is closely related to .plist, in that the property list (or .plist) is an xml file in itself. Hence, you could download a stream of xml data, then use it in your app using the same programming rubric as you would, adjusting a property list. Hence, receiving xml data from the web, or uploading such a list, maps nicely to xml persistence.
AWS also proposed the AWS-Persistence library, to support synchronizing your core data collections with their online databases. This could provide helpful by 1) having a user populate data locally via Core Data, then lazily/opportunistically uploading the list. For your purposes (grocery shopping list), this could provide immediacy to the user, while giving your server an interesting big-data opportunity (analyze user transactions, provide recommendations, sell ads, etc).
Hope this gets future visitors tapping into the wealth of what IOS provides -- peace!

Resources