coredata cloudkit sync predicate - swift

I'm not sure if this is possible but hope that it is.
My app is more complicated that this example, so I'm using this to explain.
The iOS app offers e-books and stories which are organized by library, so a user can subscribe to a library CKShare and have access to all the books in that library, potentially tens of thousands of books. Obviously one wouldn't want to duplicate the entire library from CloudKit to the local CoreData store, so I'm wondering if there is a way of filtering what gets synched to the local store via a predicate. The predicate might allow the user to only duplicate a genre (fiction) and/or author (Tom Clancy) such that the local store only has a few dozen books instead of tens of thousands. The nature of the app is that it is important to be able to access the books/stories desired off-line, so caching the desired books is necessary.
I realize that if I was doing the sync manually vs taking the default core data -> cloudkit sync this is doable, but I'd like to use the default sync mechanism and apply a filter. Can this be done and if so, how?

Related

Store CoreData in iCloud

I am currently creating a macOs application that stores customer data in a CoreData database.
Now I want that data to be stored in the iCloud. The idea is that every user has its own data in his iCloud. If he uses more than one Mac/iOS device he can access his data.
So I don't a centralized data storage for all customers but a data store for each customer separately.
I have read through some topics regarding CloudKit but was confused about it in general:
CloudKit provides a data storage for global data (e.g. I want to store data of customer)
Is there a possibility to story CoreData to an iCloud account of every customer?
If so is this possible by CloudKit or do I have to use a third party lib like Ensembles? (That mentioned there was a thread of 2016 saying that Apple dismissed the possiblity to use CoreData via iCloud but only 3rd party libs like Ensemble would work now)
Can someone give me his experience in this?
Thank you
CloudKit is quite extensive. It provides three types of database:
Public, which can be shared by everyone.
Private, which is specific to one iCloud account.
Shared, which is someone's private database, but which you have been given access to.
This gives you plenty of options, and the case you are asking about, where data is shared between the devices of a single iCloud user, fits nicely into the private database. In other words, CloudKit would work very well for you.
As others have already stated, CloudKit provides you the online storage you need to move data between devices, but it doesn't provide a complete mechanism for that. That is where frameworks like Ensembles come in; they are built on top of CloudKit and other services to handle all the bookkeeping involved in keeping two devices separated in time and space in sync. (Disclaimer: I am the developer of the Ensembles framework.)
You don't have to use a framework like Ensembles; you can just communicate with CloudKit directly, but you should not underestimate how much time and skill it would take to develop a fully syncing app with Core Data. Depending on your dataset, there can be a lot of gotchas. Ensembles and similar frameworks do a lot for you:
Ensuring changes are played back in the same order on every device
Handling concurrent changes on two different devices
Removing old and redundant data
Keeping memory usage low by providing batching, which is very important on iOS
In short, you can do it yourself, but I wouldn't recommend it. If you want Core Data sync, I recommend Ensembles, or to look at other libraries like Seam (I have not used this, but it seems popular).
If you are not married to Core Data, you could look at options like Realm and Firebase, which effectively handle the sync problem and the client API in one hit.

How to store large user-specific data

So I'm in the middle of planning a little web app that will require quite large amounts of data stored on a user level, in one case, the system would take a large object from a system level and make a "user specific" version, a user can have multiple ones of these. Simplest would be to compare it to a form stored in a google spreadsheet, where the user is expected to use the template spreadsheet, then change not only the answers but also the question.
Security wise I am quite OK
In the second case there is requirement to store multiple objects, size about 250k to maybe 3mb, once again on a user specific level, with a potential to move it to a system level so additional users can access it. As an example, say the user can upload pictures, but may not want to share all of them. However, a user may choose to "publish" a small number of them because they are happy with those specific pictures.
What design patterns should I consider using specifically around web apps where the user have decent amounts of data? For example, would it make most sense to use a single large database and have a table that keeps track of resources or create separate tables per user?
I have considered putting it all in a mongo database.
Your approach may be wrong.
If you want to store user based binary data and make it accessible for the user itself or the community, you would need a hierarchic structure like so:
userid1
pic1,pic2,pic3
userid2
pic4,pic5,pic6
community
pic7,pic8
You could then grant read permissions to "community" for all users, and permission for each user to its own directory.
Usually there is nothing wrong using a database to store binary files if you consider partitioning, role permissions and an applicable interface to access the data.
My suggestion is to use a binary repository like Artifactory.
It provides hierarchic structures, simple search queries using HTTP requests and has caching abilities for frequently queried objects.
I also think that http requests are a lot easier to use and also there is an abstraction layer to the data which is more secure.
Artifactory is free.

Constructing Autocomplete Based on A History of Past Searched Terms

So I am working on an iOS search where I have to implement a keyword search. I have used a custom view controller with a Search Display Controller object embedded into it. What I want to do is be able to store the search terms somewhere when the search button is clicked. I have thought of two ways:
store them locally in the device and query them up whenever a search is performed
store them in the web app this iOS app is connected to and perform a GET request to the web app whenever a search is performed
The second one I know how to do but I have no idea how to do the first one.
SO how do I store the search terms locally? Also, what would be a better option? The first, the second, or another?
EDIT: A remote API holds the data I am querying. I want to mimic the google search app functionality, in which it stores maybe 10-20 keywords that are searched by the user.
Thanks in advance!
It's tough to recommend with more understanding of the data and usage. For example, number of keywords? keyword list static or grows? keywords shared? what are you searching - local or remote?
EDIT: You clarified 10 - 20 strings. In that case, consider something as simple as -[NSArray writeToFile:atomically:] and just persist in a file. If you read and write in NSArray, you can work on them very quickly in memory.
Original:
If you store locally and it's a growing dynamic set of keywords, I would recommend CoreData or Sqlite directly. Sqlite is a very fast efficient local DB. If you do sqlite, checkout fmdb on github. It's an objective-c wrapper.
Concerning the pros and cons:
Local storage will be faster - you won't have network latency. Especially if you want to do type ahead queries on key stroke. Keeping in memory is even faster.
Consider how much data you're storing. How many key words are there? Is it feasible to store on the device in a DB or a file?
Do you want the keywords to be shared from multiple users? In that case either storing on the server or a combination of storing on the server and syncing to the device is needed.
Do the keywords grow over time based on usage? In that case a local database is better.

MongoDB permissions-based modelling problem

I'm trying to model a simple, experimental app as I learn Symfony and Doctrine.
My data model requires some flexibility, so I'm currenty looking into the possibility of using either an EAV model, or document store in MongoDB.
Here's my basic requirements:
Users will be able to store and share their favourite things (TV prog, website, song etc).
The list of possible 'things' a user can store is unknown. For example, a user may want to store their favourite animal.
Users can share their favourite things with other users. However, a user can decide what he / she shares with each other user. For example, a user may share their favourite movie with one user, but not another.
A typical user will log in and view all the favourite things from their list of friends, depending on what his friends have decided to share. The user will also update their own favourite things, which will be reflected when each other users views their own profile. Finally, the user may change which of his friends can see what of his favourite thing.
I've worked a lot with Magento, which uses the EAV model extensively. However, I'm adding another layer of complexity by restricting which users can see what information.
I'm instantly drawn to MongoDB as the schemaless format gives me the flexibility I require. However, I'm not sure how easy (or efficient) it will be to access the data once it's saved. I'm also concerned about how changes to the data will be managed, e.g. a user changes their favourite film.
I'm hoping someone can point me in the right direction. This is purely a demo app I'm building to further my knowledge, but I'm treating it like a real-world app where data access times are super-important.
Modelling this kind of app in a traditional relational DB makes me sweat when I think about the crazy number of joins I'd need to get the data for one user.
Thanks for reading this far, and please let me know if I can provide anymore information.
Regards,
Fish
You need to choose a model based on how you need to access the data.
If you just need to filter out some values when viewing the user profile, a single document for each user would work quite well, with each favorite within that having a list of authorized user/group IDs that is applied in the application code. Both read and write are single operations on a known document in this case, so will be fast.
If you need views across multiple profiles though, your main document should probably be the favorite. You'll need to set up the right indexes, but performance shouldn't be a problem.
Actually, the permissions you describe don't add that much complexity to an EAV schema - as long as attributes can have multiple values the permissions list is just one more attribute.

iphone data migration and application design

I'm working on an application that has a read-only database shipped with it.
The user will run the application and be able to select a series of "favourites" from the database which will appear in there "favourites" tab bar section. I.e. storing the primary keys.
With each update to the application the read only data will potentially contain more entries or have things like spelling mistakes fixed etc.
I'm using Core Data but I'm unsure whether to use it for storing the users "favourites" as-well. As - to my way of thinking - this might cause headaches for migration. Is this the case?
Should I consider storing the "favourites" in a plist perhaps and perform some sort of query to retrieve the records? Any recommendations?
Also what internal pieces of an iphone application are kept (or can be kept) during an update?
Phew I think that's it.
Thanks for any answers you might have.
Cheers,
Matt
I'm using Core Data but I'm unsure
whether to use it for storing the
users "favourites" as-well. As - to my
way of thinking - this might cause
headaches for migration. Is this the
case?
If you're going to port the app to another platform, then Core Data is not the way to go. And since we are talking about a static database, I'd keep it simple - read it once, do what you need with it and close it and forget about it. Not like a real database where you're doing multiple GETs and some amount of additions, modifications and deletions.
Should I consider storing the
"favourites" in a plist perhaps and
perform some sort of query to retrieve
the records? Any recommendations?
Your database could be a plist too. After the user selects their favourites, you can easily store them in yet another plist. This one goes in the Documents or Prefs folder.
When you release a new app, you should probably compare the favourites with the new entries to correct any typos or other changes, if applicable.
Also what internal pieces of an iphone
application are kept (or can be kept)
during an update?
I believe that your app is replaced but your Documents and Preferences folders are kept intact.