I'm currently working on a project that uses CoreData for data saving in swift, and for the purpose of synchronization I wanted to use iCloud, and the first thing I thought was on the CoreData iCloud implementation, but since it's now marked as deprecated I started using CloudKit, and everything works fine until I try to make a backup of the information after an internet connection is stablished (in case of failure when the information should be updated), the app does not store files, just data, all CKRecords are working fine.
My questions are:
Can you synchronize the information after the application is terminated?
Does CloudKit connect to the automatic iCloud synchronization, the one that happens when the device is plugged and has an internet connection.
The current structure is:
CoreData for local saving and withdrawal of data, and CloudKit for Cloud synchronization.
So far I understand that: CloudKit does not interact directly with CoreData and all actions involving data synchronization must be done with the Api calls.
Thank you for your help and if I forgot something please let me know.
1) When your app is terminated it isn't running so you can't sync anything. You would need to re-launch your app (possibly into the background?), but there are some serious limits to what you can do to have that happen without user intervention. Here's a couple threads that might shed more light: Launch app in background automatically? and Will iOS launch my app into the background if it was force-quit by the user?
2) Out of the box CloudKit doesn't do anything 'automatically', it does what you tell it to do. You will need to set it up to fire at appropriate times in your code (when something changes), and in response to push notification for changes from other devices.
Related
I am designing an architecture for an iOS SwiftUI app and I have no experience with it so I need to clarify few things.
My app will use these datasources:
Bluetooth device
API
CoreData or Realm
Bluetooth device sends data regularly (every 5 minutes) and I have to be able to get them even the app is in the background (or terminated) if possible. Data should be stored somewhere and synced to the API when connected.
Also app should be capable of determining when to use persistent storage and when to use API. One idea is that I would always use for example CoreData and data received from bluetooth device would be stored there (it should automatically rerender view). API will be requested regularly in the background, data from API will be compared with local data and synced appropriately.
I dont’ know, where should I start. I researched commonly used architectures and I really like hexagonal and clean architectures, but I can’t image how to use it correctly.
I didn’t find any resources mentioning switching datasources as the user is online/offline. If is it appropriate to use always CoreData in the app or if I should switch datasources and synchronize with CoreData in the background.
We have finished writing an iPhone App that uses coredata.
In further versions we plan to add an iPad App that is able to display the data collected by the iPhone App (and of corse modify, use it) to give more interaction possibilities to the user.
My question is: Is it possible to move existing coredata (of already installed apps on iphones) to the cloud and read that data out with an iPad application?
If yes: can you point me in the right direction of where to start?
If no: is there another alternative to access coredata created with an iPhone App with an iPad app?
When using Core Data's built in iCloud support it doesn't matter what kind of device you're on, only that the Core Data stack is initialized the same way. Any iOS device or Mac can use the same iCloud store, and data created on one can be read on another.
One crucial detail though: If you already have a data store and you add iCloud support, those pre-existing records do not automatically get migrated to the cloud. iCloud works based on transaction logs, and transaction logs are only created when you save changes. Existing data that doesn't immediately change generates no transactions, and therefore doesn't go to the cloud.
If you have existing data when you add iCloud, you'll need to migrate the data to a new data store to force transactions for those existing records. You can do this fairly easily using NSPersistentStoreCoordinator's migratePersistentStore:toURL:options:withType:error: method. It's not hard, but it's not always obvious that it's necessary.
To get started, I first suggest watching Apple's WWDC videos on iCloud-- especially WWDC 2012's session 227, Using iCloud with Core Data. Next, I suggest extreme caution, because as of today Core Data's iCloud support is still, shall we say, far from being the most reliable of Apple's APIs.
I have an iPhone (iOS) app that keeps data in a local SQLite database on each device. The app is used to manage a virtual bank account for kids to track their allowance, spending, savings, etc. (KidsBank and KidsBank Free). I am getting a lot of requests from parents to provide a sync capability between parents and possibly even their children's iOS devices.
I have considered several options, but all are tedious and non-trivial since this basically requires database replication or a new architecture. Any transaction on any device ideally should appear (sync) to all devices in the family (as immediately as possible).
Ideally, I would like the sync to be automatic & hands off
Options include
(1) Use of iCloud
(2) Use a direct network connection between devices (wifi)
(3) Use of a server side database and web service (JSON/RESTFul)
(1) iCloud
PRO: iCloud provides distributed file sync
CON: iOS 5 required, SQLite database files can not be synced via iCloud, classic database replication (and non-trivial)
Using iCloud is a strong consideration. Devices can write a custom transaction log to an iCloud file where there is one file for each device identified by a unique device ID. Global unique ids (GIDs) and last change timestamps are added to each table. All participating devices will write a unique device ID to a separate file in iCloud. Upon app launch or upon log file change, the app running on a specific device will load all transactions but not those generated on their own device from the files via iCloud. The last participating device to load the transaction will remove the transaction from the file. If the device is not the last participating device, it simply signs off on the transaction and allows the file to sync via iCloud. There may be better algorithms, but the basic idea is the same - using iCloud to push around change logs.
(2) A direct wifi connection will allow two devices to manually sych.
PRO: Not as complicated to manage the sync process
CON: Users must both select to sync from their apps while connected on wifi
(3) Move the entire database or manage transactions on a server.
PRO: Sync is no longer required
CON: Typical issues for a web-driven app. Would need to rewrite the database service layer (currently in SQL) to use a remote web service. Cost of running a server (I would use AWS).
Can anyone offer some experience in syncing SQLite between multiple devices? I'm leaning in the direction of using iCloud to push around transaction logs. I'm trying to minimize cost and complexity.
Moving to iCloud is probably the best solution, as it is proven and made by Apple. You don't need to worry to much about the iOS 5 requirement, as according to most stats over 90% use it. iOS 5 is free to upgrade to. You could then rename your old version as Lite, and continue without syncing.
Syncing is probably one of the hardest things you do.
One solution I made is that all changes to a database leave a log, with timestamp, uniqueid and couple of other things to make sure the transaction is totally anonymous and totally unique. I have made an extremely simple web service that has two operations, you can add transaction to it, so I sync whenever the user is on wifi, so I push all changes, receive a result from the server, then delete the transaction records as they are synced.
The other action is to fetch the records, send the timestamp of last sync, userid and other.
All data is sent using JSON and received as such. It can easily handle tens of thousands of users, running on a small Amazon EC2 server.
This is pretty much how iCloud works, but I made this solution before iCloud. Now I am going to iCloud, but probably need to keep the server running for 1 more year or so, depends on usage.
Hope this helps you.
After finding time to get back to working on the app and also with time passing and Core Data iCloud replication maturing, I converted my app to Core Data (NSSQLiteStoreType) and monitor notifications such as persistentStoreDidImportUbiquitousContentChanges. Using lightweight migrations too. Working well.
I have an app that uses an SQLite database. With the advent of iCloud on the rise I'm trying to figure out a good architecture for syncing data between devices. So lets say my app runs on an iPhone, an iPad, and a Mac. How can I keep data in my DB up-to-date on all devices?
My first thought was, I can put the database in the cloud and send transactions. But the device may not always been online and the users need their content at anytime, so that wont work. My other thought was to continue using the local db, and then when a connection is made, to send the cached data to the central db. The problem is I have no ideal where to even begin on something like that. How would I know which data has been sent and not sent, which data to actually send when a connection is made, etc.
So this is my question (we don't have to get into iCloud specifics), using an SQLite database and iCloud (or any storage medium), how can I sync data between multiple devices, but still have the most recent data stored locally on the device?
You might want to checkout Couchbase Mobile. This would help with the synchronization you are looking for.
If you have a significant investment into CoreData, then you may want to look at writing your own NSIncrementalStore to support writing data to and from a key value store.
iCloud is only going to be a good solution if your data is sandboxed to a specific user. If you have multiple users that want to view the same data then it won't work.
i have an iphone app that uses coredata to store its contents. users often ask me if i could provide a way to sync data between their mobile devices (ipod/iphone/ipad). as of now, i have no idea on how to achieve this.
i found zsync, but this seems to depend on a osx version of the app (which i dont have). i also read about upcoming iclouds sync features, and it seems to be what i need - however i think its not possible to sync coredata contents, but text-based contents only (e.g. xml storage files). is this true?
another way i was thinking of was to abuse the eventkit api to sync via a user-provided calendar. since my app is mainly managing events, which can optionally be stored in a user-calendar (in addition to coredata storage), syncing through a calendar would seem good to me. however i think syncing might break, e.g. when the user chooses not to syncronize the whole calendar but only like 3 months in the devices settings/account settings.
anyone got an idea of how my approach should be like? any tips?
Syncing device to device (if that is what you are trying to achieve) can be quite tricky. You could implement your own discovery and data-transfer protocol and work something out that way, but it could be quite a bit of work.
Syncing device to server to device is a bit more straightforward, assuming that you already have a server with some form of registration/login system. Then you just need a way of communicating your current database state up to the server, and then back down again from the server to other devices. Again there is a fair bit of work involved in doing this, but at least the logic of working out which devices sync with which other devices and how they transfer data from one to the other is all implicit in the workings of the server.
As for iCloud, the programmatic content that you sync through it needs to be derived from UIDocument, so it will not help you with generic Core Data entities.
If you're looking for an out-of-the-box solution that will sync all of your Core Data content from one device to another with no custom code, then there really isn't one. The closest you can reasonably get would be to ship the entire .sqlite file that your app uses from one device to another, overwriting the target devices .sqlite file. That works fine if your sync only needs to be unidirectional, but obviously is not appropriate for other use-cases. Perhaps you could use this model with iCloud, if you can get it to sync your app's entire .sqlite file as an atomic entity.