BLACK FRIDAY: Save 50% on all my Swift books and bundles! >>

What is a suitable method for data synchronisation with other users in Swift?

Forums > SwiftUI

Hi, I am designing a simple task manager for a household in SwiftUI. I would like the app to synchronise the content data across the devices of the various users part of the household. To me, this seems like a simple enough process potentially. Which approach is best suitable with the SwiftUI framework?

Update: View my response below (2nd post) for a better explanation of my question.

Initial post:

The data model of the app is very simple at the moment; essentially a collection of tasks that each feature a title, description and assignment to a user. Running the app locally, without synchronisation implemented yet, allows me to make use of the SwiftUI's framework declarative programming and elegant design.

I realise that to implement synchronisation with other users' devices unavoidably means I need to implement code and adapt existing code. For years, I have browsed articles and tutorials on data sharing in iOS apps. Options I have explored are Core Data, CloudKit, manual API fetching from server and third-party options like Realm. The underlying, unnamed issue seems to be that SwiftUI is still young and data frameworks don't yet offer an elegant integration.

I am looking for an approach that integrates best with SwiftUI's elegance and framework with respect to data propagation (ObservableObjects and such).

  • Core Data provides a way to store data persistently and is fairly integrateable with SwiftUI, given it's Apple's own framework; even @FetchRequests are available. However, it does seem quite old (for example in use and interpretation of nil values of object members) and uses classes instead of structs. I have read quite some tutorials on using Core Data with SwiftUI, but these range from being very unscalable (e.g. writing the full CRUD, repetitive operations within View layers) to conversion between structs and classes and apparent instability w.r.t. synchronisation (after a successful Core Data save, also adding a struct to some observed @Published list to keep using SwiftUI's data propagation mechanisms).

    • Core Data itself does not necessarily offer sharing between devices, it is merely a storage method. It does provide an interface with CloudKit, but this only synchronises its state within one user's iCloud (e.g. NSPersistentCloudKitContainer does not support a shared scope). This seems to imply CoreData itself cannot provide the functionality I am looking for.
  • CloudKit itself is also provided by Apple and offers features such as shared records, which does allow sharing between users. However, I cannot find a good documentation or explanation on how to combine SwiftUI and CloudKit to maintain a synchronised state between users.

  • Alternatively, using Codable structs would allow to convert server responses to local data or send local data to a server. I have also created CRUD API's previously, so implementing the server side should be no problem. However, with the task of merging conflicting edits and notifying users' devices I have no experience, so this seems a little too complex to do right.

  • Then lastly, Realm also offers a remote database management system, but the implementation in SwiftUI seems hacky at best, with a lot of overhead code.

Concluding, what is in your experience and opinion the best/most elegant or/most viable way, for a simple SwiftUI app, to implement data synchronisation for a simple data model across multiple users' devices? Or, is this not available at this time? (A positive answer here would be equally informative :-)

I would love to hear your ideas, Kind regards, Isaiah

3      

Well, that's what separation of concerns is for... right?

Your network layer, model, and data processing all can and should be done without worrying about the UI. And while SwiftUI is not just about the UI as a framework, once you understand the passing of data, you really can do anything you want.

So essentially what I am saying is: Choose the sync option that you have access to and are comfortable with. Learn (if you haven't already) how to pass data around with SwiftUI. and just implement them separately.

Now if you want resouorces I would strongly recommend you check out Donny Wals website and his book: Practical Combine which is where most of the @Observable etc... are from 😉

3      

Thank you for your reply @MarcusKay That is a good remark.

Perhaps I should have stressed SwiftUI less so in my question. I would like to use SwiftUI for the UI design, but the data synchronisation doesn't live there indeed.

Let me then rephrase my question more in general. How can I implement simple data sharing between users in Swift? Then, does anyone have some pointers on how to integrate that data layer with SwiftUI?

For example, CloudKit allows you to store data in CKRecords that can be shared and databases that can be subscribed to. How can this data be persisted? How can this best interact with Combine's ObservedObject, preferably in the form of structs? Or is this not preferred?

The CoreData CloudKit intergration seems the best shot right now, and the only thing I can find in tutorials. However, it does not allow for data sharing (NSPersistentCloudKitContainer does not support a shared scope) and Apple engineers recommend implementing the sharing through CKShare and such yourself. Does anyone know of a good resource on how to implement this sharing mechanism, persisting data and storing this in an ObservedObject?

Alternatively, if there are experienced Swift programmers here that would state 'This topic is advanced and not yet well documented, provided or implemented in Swift(UI)' I would love to hear that as well. Possibly Apple does not provide much resources for this, and the current main approach is to rely on third-party database frameworks (Realm) instead? I do notice an almost absolute absence of tutorials on data sharing between users, especially in SwiftUI, while it is such a simple concept or requirement.

Many thanks in advance!

3      

Hey Did you solve this? I have the same issue as you had in my project.

3      

hi,

glad to see this question resurface, since it's something i will be adding to an app (very soon, i hope).

Isaiah wrote that

Core Data itself does not necessarily offer sharing between devices ... only synchronises its state within one user's iCloud (e.g. NSPersistentCloudKitContainer does not support a shared scope). This seems to imply CoreData itself cannot provide the functionality I am looking for.

good news: things have changed!

be sure to check out the WWDC21 video Build apps that share data through CloudKit and Core Data, since a new capability added to NSPersistentCloudKitContainer in iOS 15 and MacOS 12 is the ability to share data with other users.

i think this will be my sharing solution going forward.

hope that helps,

DMG

PS. here's where you can some related Apple sample code, although i am not sure this is directly on-point. if you follow the Apple Developer Forums, look for the tag "wwdc21-10015"

3      

Oh I wish it was a SwiftUI sample for me as a newbie 😳

3      

Any success with sharing on NSPersistentCloudKitContainer and SwiftUI yet? Dying to get this implemented.

3      

I'm also looking for similar help, but I only want to sync data across devices logged into the same account, like my iPad and iPhone.

2      

Save 50% in my WWDC sale.

SAVE 50% All our books and bundles are half price for Black Friday, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.